Установка ComboBox.SelectedItem в XAML на основе соответствующего объекта

Я создал шаблон ComboBox, который в основном действует как простая цветовая палитра. Он заполнен списком SolidColorBrush объектов.

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

Я пытаюсь установить свойство SelectedItem для ComboBox на основе цвета из моего источника данных. Поскольку моя комбинация заполнена объектами типа SolidColourBrush, а мой преобразователь привязки возвращает SolidColorBrush, я предположил, что это будет так же просто, как сказать:

SelectedItem="{Binding Color, Converter={StaticResource StringToBrush}}"

Однако... не работает :(

Я проверил, что привязка работает за кулисами, используя точно такое же значение для свойства Background файла ComboBox.

Итак, ясно, что я не могу просто сказать SelectedItem = [что-то], где это [что-то] в основном является объектом, равным элементу, который я хочу выбрать.

Как правильно это сделать? Конечно, это возможно в стиле только для XAML с использованием привязки, и мне не нужно делать какой-то неприятный С#, перебирая все элементы в поле со списком, пытаясь найти совпадение (это кажется ужасно старой школой)...?


person Andy T    schedule 15.04.2010    source источник
comment
Предлагается переопределить функцию Equals функции SolidColorBrush . По умолчанию Equals при сравнении двух элементов проверяет, совпадают ли ссылки. Вы можете изменить это поведение и сделать так, чтобы Equals также проверяло, например, совпадает ли цветовой код. Проверьте этот ответ для справки.   -  person Athafoud    schedule 12.12.2016


Ответы (2)


Вы можете привязать данные SelectedItem к выпадающему списку. Насколько я понимаю ваше описание, у вас есть коллекция шестнадцатеричных строк и свойство SolidColorBrush с именем Color. Приведенный ниже код обновляет свойство Color при изменении выбранного элемента.

XAML:

<Window x:Class="SelItemTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:SelItemTest="clr-namespace:SelItemTest"
    Title="Window1" Height="300" Width="300">

    <Window.Resources>        
        <SelItemTest:StringToBrushConverter x:Key="StringToBrush" />        
    </Window.Resources>

    <StackPanel Background="{Binding Path=Color}">
        <ComboBox
            ItemsSource="{Binding Path=Colors}"
            SelectedItem="{Binding Path=Color, Converter={StaticResource StringToBrush}}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <Border Background="{Binding}" Height="20" Width="100" />
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </StackPanel>

</Window>

Код позади:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;

namespace SelItemTest
{
    public partial class Window1 : Window, INotifyPropertyChanged
    {
        public Window1()
        {
            InitializeComponent();

            Colors = new List<string>();
            Colors.Add(Brushes.Red.ToString());
            Colors.Add(Brushes.Blue.ToString());
            Colors.Add(Brushes.Yellow.ToString());

            Color = Brushes.Yellow;

            DataContext = this;
        }

        public List<string> Colors { get; set;}

        private SolidColorBrush _color;
        public SolidColorBrush Color
        {
            get { return _color; }
            set
            {
                _color = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("Color"));
                }
            }
        }

        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
    }

    public class StringToBrushConverter : IValueConverter
    {
        #region IValueConverter Members
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value.ToString();
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            Color color = (Color)ColorConverter.ConvertFromString(value.ToString());
            SolidColorBrush scb = new SolidColorBrush(color);
            return scb;
        }
        #endregion
    }
}
person Wallstreet Programmer    schedule 15.04.2010

Если вы используете шаблон MVVM, затем добавьте свойство SelectedHexColor в свою модель представления и позвольте модели представления искать правильную кисть сплошного цвета в вашем списке, из которого заполняется поле со списком цветных кистей, и обновите свойство SelectedBrush вашей модели представления на к которому привязан выбранный элемент списка.

[править] Я только что прочитал, что вы хотите избегать кода C#, потому что считаете его устаревшим. Но в этом и заключается сила шаблона MVVM, потому что вы можете проводить модульное тестирование именно этого кода, который уже представляет собой сложную бизнес-логику. Помещать это в XAML довольно небезопасно, потому что вы не можете выполнить его модульное тестирование и, следовательно, вы не можете гарантировать правильную функциональность (за исключением автоматических тестов пользовательского интерфейса, которые намного сложнее реализовать, чем модульные тесты).

С наилучшими пожеланиями,
Оливер Ханаппи

person Oliver Hanappi    schedule 15.04.2010
comment
Хммм ладно. Но я думаю, что ищу более общий ответ. Если у меня есть поле со списком со списком элементов типа Foo, а также другой экземпляр Foo, хранящийся где-то еще (скажем, в myFoo), наверняка есть способ сказать только XAML: выбранный элемент поля со списком myFoo, или, точнее, выбранный элемент списка — это Foo, который соответствует myFoo... верно? - person Andy T; 15.04.2010
comment
В этом случае вам нужно будет реализовать логику равенства значений. Для этой цели вы можете обернуть SolidColorBrush в объект, который реализует равенство значений (переопределяя GetHashCode и Equals). - person Oliver Hanappi; 15.04.2010