Как связать элемент управления WPF со свойством объекта, который находится в словаре? - PullRequest
0 голосов
/ 06 марта 2019

Я новичок в WPF и изучаю, как связать элементы управления. Я создал пользовательский интерфейс, который имеет различные элементы управления, такие как выпадающий список и спиннер (пользовательский элемент управления). Теперь я хочу связать эти элементы управления, такие как выпадающий список, со свойством объекта. Ниже приведен пример кода.

public class Parameter : INotifyPropertyChanged
{
    protected decimal m_Code;

    public decimal CODE
    {
        get { return m_Code; }
        set
        {
            if (m_Code != value)
            {
                m_Code = value;
                NotifyPropertyChanged("CODE");
            }
        }
    }

    protected decimal m_CurrentValue;

    public decimal CURRENT_VALUE
    {
        get { return m_CurrentValue; }
        set
        {
            if (m_CurrentValue != value)
            {
                m_CurrentValue = value;
                NotifyPropertyChanged("CURRENT_VALUE");
            }
        }
    }

    protected Dictionary<int, string> m_ItemsDict;

    public Dictionary<int, string> ItemsDict
    {
        get { return m_ItemsDict; }
        set
        {
            //if (m_dict != value) Not comparing dictionaries. We should set if we get this request
            {
                m_ItemsDict = value;
                NotifyPropertyChanged("ItemsDict");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}

Ниже класса - синглтон, в котором есть словарь, в котором Key - это int, а value - это объект класса параметров.

public class ParameterDB: INotifyPropertyChanged
{
    private static ParameterDB m_instance = new ParameterDB();

    public static ParameterDB Instance
    {
        get { return m_instance; }
    }

    private Dictionary<int, Parameter> m_ParamDict; 

    private ParameterDB()
    {
        m_ParamDict = new Dictionary<int, Parameter>();
        for(int i=0; i< 300; i++)
        {
            m_ParamDict.Add(i, new Parameter());
        }
    }

    public Dictionary<int, Parameter> ParamDict
    {
        get
        {
            return m_ParamDict;
        }

        set
        {
            m_ParamDict = value;
            NotifyPropertyChanged("ParamDict");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}

Теперь я хочу привязать элемент управления, скажем, к ParamDict [0] .CURRENT_VALUE. Я создал собственный класс со списком.

public class MyComboBox : System.Windows.Controls.ComboBox
{
    public readonly static DependencyProperty CodeProperty = DependencyProperty.Register(
        "Code",
        typeof(UInt32),
        typeof(FlexSIMComboBox),
        new PropertyMetadata(new UInt32()));

    public UInt32 Code
    {
        get { return (UInt32)GetValue(CodeProperty); }
        set
        {
            SetValue(CodeProperty, value);
        }
    }


    public readonly static DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value",
        typeof(decimal),
        typeof(MyComboBox),
        new PropertyMetadata(new decimal(0), ValueChangedCallback));

    public decimal Value
    {
        get { return (decimal)GetValue(ValueProperty); }
        set
        {
            SetValue(ValueProperty, value);
        }
    }

    private static void ValueChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MyComboBox myComboBox = d as MyComboBox;

        if (myComboBox != null && e.NewValue is decimal)
        {
            // Check if new value is under the limit
            decimal newValue = (decimal)e.NewValue;
            myComboBox.SelectedValue = (int)newValue;
        }
    }
}

XAML-файл:

<local:MyComboBox 
    Grid.Column="1" x:Name="myCBCtrl" Margin="0,0,0,7"   Width="180"
    HorizontalAlignment="Left"  VerticalAlignment="Bottom" IsReadOnly="true" 
    Code="{Binding CODE, Mode =TwoWay}" 
    Value="{Binding CURRENT_VALUE, Mode =TwoWay}" 
    ItemsSource="{Binding ItemsDict, Mode =TwoWay, NotifyOnTargetUpdated=True}"
    SelectedValuePath="Key" DisplayMemberPath="Value" TargetUpdated="ComboBox_TargetUpdated"
    StaysOpenOnEdit="True" SelectedIndex="0" SelectionChanged="ComboBox_SelectionChanged"/>

У меня вопрос, как мне установить DataContext для этого элемента управления на объект, который находится в словаре? Например, чтобы ParamDict [CODE]. КОД также является ключом для словаря.

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

1 Ответ

0 голосов
/ 06 марта 2019

Я разобрался, как это сделать.

<local:MyComboBox DataContext="{Binding Source={x:Static local:ParameterDB.Instance}}"
    Grid.Column="1" x:Name="myCBCtrl" Margin="0,0,0,7"   Width="180"
    HorizontalAlignment="Left"  VerticalAlignment="Bottom" IsReadOnly="true" 
    Code="{Binding Path=ParamDict[0].CODE, Mode =TwoWay}" 
    Value="{Binding Path=ParamDict[0].CURRENT_VALUE, Mode =TwoWay}" 
    ItemsSource="{Binding Path=ParamDict[0].ItemsDict, Mode =TwoWay, NotifyOnTargetUpdated=True}"
    SelectedValuePath="Key" DisplayMemberPath="Value" TargetUpdated="ComboBox_TargetUpdated"
    StaysOpenOnEdit="True" SelectedIndex="0" SelectionChanged="ComboBox_SelectionChanged"/>
...