Сложное связывание WPF: связать значение с IConverter, используя в качестве входных данных результат статического метода - PullRequest
0 голосов
/ 29 июля 2011

Мне было интересно, возможно ли иметь следующий тип привязки, и я не смог сформировать поисковый запрос, который дал бы мне окончательный ответ, или найти его где-нибудь.

Вот случай.

У меня есть ListBox с 'Items' (пользовательский класс), эти элементы отображаются с использованием шаблона элемента.Я использую конвертер для расчета фонового цвета.Смотрите ниже:

<Window.Resources>
    <local:MyConverter x:Key="myConverter"/>
</Window.Resources>

<!-- snip -->
<ListBox Grid.Row="2" Name="listBoxMaterialType" Margin="0,0,0,0" ItemsSource="{Binding Path=MyItems, ElementName=MySource}">
    <ListBox.ItemTemplate>
        <DataTemplate>
                <TextBlock Text="{Binding DisplayText}" Background="{Binding Converter={StaticResource myConverter}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Теперь для лучшей абстракции я бы хотел, чтобы MyConverter не конвертировал Предмет, а только конвертировал счет предмета.Элемент не знает свою собственную оценку, но оценка рассчитывается путем вызова MyStaticClass.MyStaticMethod (item);Таким образом, в коде я хотел бы сделать привязку следующим образом: myTextBlock.Background = MyConverter (MyStaticClass.MyStaticMethod (item));Можно ли сделать это в WPF с привязкой данных?

Ответы [ 3 ]

1 голос
/ 29 июля 2011

Традиционно именно ViewModel будет брать объект вашего домена и предоставлять данные, необходимые представлению.Это может включать добавление новых свойств, которые являются агрегатами или преобразованиями свойств модели (например, Предоставление свойства FullName путем объединения свойств модели FirstName и Surname).В вашем случае:

public class Item
{
    public string DisplayText { get; set; }
}

public class ItemViewModel
{
    private Item _model;

    public string DisplayText
    {
        get { return _model.DisplayText; }
    }

    public int Score
    {
        get { return MyStaticClass.MyStaticMethod(_model);
    }
}

Затем, используя ViewModel в качестве DataContext, вы можете привязать конвертер непосредственно к свойству Score.

1 голос
/ 29 июля 2011

Вы можете сделать много вещей, например, вы можете добавить несколько свойств в ваш конвертер, которые указывают на метод.Это могут быть, например, TargetType, TargetObject & MethodName, тогда вы можете - указав MethodName и любое другое свойство - заставить преобразователь вызывать метод для TargetObject или статически.

например, что-то вроде этого:

//<Property declarations>

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    bool staticCall = TargetObject == null;
    var types = new Type[] { value.GetType() };
    var args = new object[] { value };
    MethodInfo method;
    if (staticCall)
    {
        method = TargetType.GetMethod(MethodName, types);
    }
    else
    {
        method = TargetObject.GetType().GetMethod(MethodName, types);
    }
    var score = method.Invoke(TargetObject, args);

    //Convert score
}

(Как и во всех отрывочных фрагментах, не бездумно копируйте и вставляйте это, возможно, это отстой)

<vc:MyConverter x:Key="ScoreConverter"
                TargetType="{x:Type local:MyStaticClass}"
                MethodName="MyStaticMethod"/>
0 голосов
/ 29 июля 2011

Конечно, конвертер работает, применяя описываемую вами статическую функцию: от элемента к цвету. Все идет хорошо.

Проблема возникнет, если учесть, что цвет может измениться при некоторых условиях на счете. Как вы думаете, каким образом привязка может быть запущена для обновления значения цвета (таким образом вызывая конвертер)?

Полагаю, это скорее структурная проблема, чем техническая.

EDIT: Либо я не понимаю проблему, либо решение простое:

    public class MyConverter
        : IValueConverter
    {
        public object Convert(
            object value, 
            Type targetType, 
            object parameter, 
            System.Globalization.CultureInfo culture)
        {
            return MyStaticClass.MyStaticMethod(value as MyItem);
        }

        public object ConvertBack(
            object value, 
            Type targetType, 
            object parameter, 
            System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

Я бы также добавил Mode = OneTime в условие привязки.

Приветствия

...