Как сделать рефактор привязок данных WPF безопасным? - PullRequest
7 голосов
/ 12 сентября 2009

Итак, я работаю над своим первым проектом 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 ]

3 голосов
/ 12 сентября 2009

Вы можете использовать лямбда-выражение для выражения имени свойства вместо непосредственного использования имени:

    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 голосов
/ 12 сентября 2009

Рефакторинг опирается на поддержку инструмента, распознающую, когда определенный символ в коде (C #, XAML, config и т. Д.) Представляет идентификатор, который переименовывается.

В приведенном вами примере строковый литерал "FooProperty" не может быть на 100% истолкован как принадлежащий MyDataObject без специальных знаний о внутренней работе GridView и расширении всех других типов в WPF и других средах.

Однако в DataTemplate можно быть уверенным на 99%:

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

Я использую (и клянусь) плагин IDE под названием ReSharper (он же R #), который очень хорошо разбирается в подобных вещах. Если вы переименуете FooProperty, R # автоматически переименует свойство.

В вашем примере, если бы вы переименовали свойство, R # все равно пригодился бы. Он находит все экземпляры строки в литералах (ваш случай) и комментариях (очень полезно, если вы закомментировали некоторый код и можете раскомментировать его позже). Вам предоставляется древовидное представление, отображающее каждый литерал в контексте, и вы можете проверить / снять отметку с отдельных операций / файлов / папок / проектов перед продолжением.

Если ваш бюджет позволяет, получите R #. Если ваш бюджет не позволяет, загрузите пробную версию, и к концу ее бюджет уйдет. Убедитесь, что вы распечатали копию сочетаний клавиш для улучшения вашего обучения.

0 голосов
/ 12 сентября 2009

Вы можете использовать отражение, чтобы определить названия вашей собственности. Конечно, это проблематично, если у вас есть более одной привязки на класс, поэтому, возможно, дополнительно использовать пользовательские атрибуты (которые также доступны через отражение), чтобы получить «подсказки» относительно правильного поля привязки, с которым должно быть связано именованное свойство.

Это очень хорошо может закончиться тем, что мы просто переместим неповторяемую магическую строку в другую часть приложения, хотя я не могу сказать, что я пробовал это, и это сработало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...