代码之家  ›  专栏  ›  技术社区  ›  Brian Gideon

如何使WPF数据绑定重构安全?

  •  7
  • Brian Gideon  · 技术社区  · 15 年前

    所以我正在完成我的第一个WPF项目,我很喜欢到目前为止所看到的。学习曲线比我预期的要多,但是WPF还是很酷的。然而,我在数据绑定概念方面遇到了一些困难。我面临的一个具体问题是,如何使数据绑定声明重构安全?考虑这个例子。

    public class MyDataObject
    {
      public string FooProperty { get; set; }
    }
    
    void Bind() 
    {
      var gridView = myListView.View as GridView;
      gridView.Columns.Clear();
      gridView.Columns.Add(
        new GridViewColumn() 
          { 
            Header = "FooHeader", 
            DisplayMember = new Binding("FooProperty")
          }
        );
      List<MyDataObject> source = GetData();
      myListView.ItemsSource = source;
    }
    

    那么,如果我将数据对象上的Fooproperty重命名为其他名称呢?数据绑定将无效,我不会得到编译错误,因为绑定是通过文本声明的。有没有一种方法可以使绑定更安全地重构?

    3 回复  |  直到 15 年前
        1
  •  3
  •   Thomas Levesque    15 年前

    可以使用lambda表达式来表示属性名,而不是直接使用该名称:

        protected static string GetPropertyName<TSource, TResult>(Expression<Func<TSource, TResult>> expression)
        {
            if (expression.NodeType == ExpressionType.Lambda && expression.Body.NodeType == ExpressionType.MemberAccess)
            {
                PropertyInfo prop = (expression.Body as MemberExpression).Member as PropertyInfo;
                if (prop != null)
                {
                    return prop.Name;
                }
            }
            throw new ArgumentException("expression", "Not a property expression");
        }
    

    您可以这样使用它:

    ...
    DisplayMember = new Binding(GetPropertyName((MyDataObject o) => o.FooProperty))
    ...
    

    好吧,有点冗长…如果您想要更简短的内容,还可以创建一个助手方法:

    public Binding CreateBinding<TSource, TResult>(Expression<Func<TSource, TResult>> expression)
    {
        return new Binding(GetPropertyName(expression))
    }
    
    ...
    DisplayMember = CreateBinding((MyDataObject o) => o.FooProperty)
    ...
    

    这样,如果重命名属性(当然,XAML中除外…)重构应该可以很好地工作。

        2
  •  2
  •   Drew Noakes    15 年前

    重构依赖于工具支持识别代码中的特定符号(C、XAML、config等)何时表示要重命名的标识符。

    在您给出的示例中,字符串文本 "FooProperty" 不能100%理解为属于 MyDataObject 不了解 GridView 以及通过扩展WPF和其他框架中的所有其他类型。

    但是,在数据模板中,99%的人可以确定:

    <DataTemplate DataType="{x:Type local:MyDataObject}">
        <TextBlock Text="{Binding Path=FooProperty}" />
    </DataTemplate>
    

    我使用一个名为 ReSharper (又名R),这是一个非常聪明的关于这类事情。如果您重命名 FooProperty ,r将自动为您重命名属性。

    在您的示例中,如果您要重命名该属性,r仍然可以使用。它可以在文本(您的案例)和注释中找到字符串的所有实例(如果您注释了一些代码,以后可能会取消注释,则非常有用)。我们为您提供了一个树视图,它在上下文中显示每个文本,您可以在继续之前选中/取消选中各个用法/文件/文件夹/项目。

    如果你的预算允许,得到R。如果你的预算不允许,下载一个试用版,在它结束时,你的预算将找到空间。确保打印出快捷键的副本,以改善您的学习体验。

        3
  •  0
  •   Mikeb    15 年前

    可以使用反射来确定属性的名称。当然,如果每个类有多个绑定,那么这是有问题的,因此可能还使用自定义属性(也可以通过反射获得)来获取有关命名属性应绑定到的正确绑定字段的“提示”。

    很好的结果可能只是将不可重构的魔术字符串重新定位到应用程序的另一个部分,不过,我不能说我已经尝试过这个方法,并让它工作了。