WPF - динамический доступ к определенному элементу коллекции в XAML - PullRequest
1 голос
/ 01 июня 2010

У меня есть источник данных («SampleAppearanceDefinitions»), который содержит одну коллекцию («Определения»). Каждый элемент в коллекции имеет несколько свойств, в том числе цвет, который мне интересен здесь.

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

Text="{Binding Source={StaticResource SampleAppearanceDefinitions}, Path=Definitions[0].Color}"

Единственная проблема в том, что это требует от меня жесткого кодирования индекса элемента в коллекции Definitions (я использовал 0 в приведенном выше примере). На самом деле я хочу получить это значение из свойства моего текущего DataContext ('AppearanceID'). Можно представить себе правильный код, чтобы выглядеть следующим образом ...

Text="{Binding Source={StaticResource SampleAppearanceDefinitions}, Path=Definitions[{Binding AppearanceID}].Color}"

... но, конечно, это неправильно.

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

Любая помощь будет принята с благодарностью!

Спасибо!

AT

Ответы [ 3 ]

1 голос
/ 01 июня 2010

MultiBinding ваш друг здесь:

Предполагается, что у вас есть TextBlock:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding Converter="{StaticResource AppearanceIDConverter}">
            <Binding Source="{StaticResource SampleAppearanceDefinitions}" />
            <Binding Path="AppearanceID" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

И определите MultiValueConverter для возврата того, что вы хотите видеть:

public class AppearanceIDConverter : IMultiValueConverter
{
    #region IMultiValueConverter Members

    public object Convert(object[] values, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        List<item> items = (List<item>)values[0]; //Assuming its items in a List
        int id = (int)values[1]; //Assuming AppearanceID is an integer
        return items.First(i => i.ID == id).Color; //Select your item based on the appearanceID.. I used LINQ, but a foreach will work just fine as well
    }

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

    #endregion
}

Конечно, вам нужно будет установить конвертер как ресурс в вашем словаре ресурсов, как вы делали SampleAppearanceDefinitions. Вы также можете отказаться от мультисвязывания и использовать обычную привязку к AppearanceID с IValueConverter, если можете получить доступ к коллекции SampleAppearanceDefinitions с помощью кода;).

Надеюсь, это поможет

0 голосов
/ 18 августа 2010

MultiBinding может действительно работать, если ваш список находится на модели представления вместо статического ресурса. Я был удивлен, увидев, что объект, передаваемый представлению, фактически является указателем на объект в модели, поэтому изменение объекта в представлении (например, ввод нового теста в текстовом поле) напрямую влияет на объект модели. 1001 *

Это сработало для меня. Метод ConvertBack никогда не используется.

public class PropertyIdToPropertyConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values.Length == 2)
        {
            var properties = values[0] as ObservableCollection<PropertyModel>;

            if (properties != null)
            {
                var id = (int)values[1];
                return properties.Where(model => model.Id == id).FirstOrDefault();
            }
        }

        return null;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
0 голосов
/ 01 июня 2010

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

Это свойство, скажем «CurrentAppearance», будет предоставлять свойство Color, которое вы можете связать с вашим Xaml:

Text="{Binding CurrentAppearance.Color}"

что более понятно.

Как общий совет: не портите свой Xaml сантехническим кодом: Xaml должен быть максимально читабельным, особенно если вы работаете с командой дизайнеров, которые не имеют навыков кодирования и не хотят беспокоиться о том, как вы управляете данными.

Более того, если позже вы решите изменить способ управления данными, вам не придется менять свой Xaml.

...