双向数据绑定与WPF中的字典

Way*_*inn 25 c# data-binding wpf xaml dictionary

我想绑定Dictionary<string, int>ListViewWPF中.我希望做这样一种方式,ValuesDictionary通过数据绑定机制得到更新.我不想改变Keys那个Values.我也不在乎添加新的映射Dictionary.我只是想更新现有的.

设置词典为ItemsSourceListView不做到这一点.它不起作用,因为ListView使用Enumerator访问其内容,Dictionary并且该枚举的元素是不可变KeyValuePair对象.

我目前的调查尝试使用该Keys属性.我将此分配给我的ItemsSource属性ListView.这并不让我来显示Keys,但我不知道有足够的了解WPF的数据绑定机制来访问ValuesDictionary.

我发现了这个问题:在XAML中访问codebehind变量但仍然无法弥合差距.

你们中的任何人都知道如何使这种方法有效吗?有没有人有更好的方法?

看来,作为最后的手段,我可​​以构建一个自定义对象并将其粘贴List到我重新创建/更新我的内容中,Dictionary但这似乎是一种绕过内置数据绑定功能而不是有效利用它的方法.

Ray*_*Ray 20

我不认为你能用词典做你想做的事.

  1. 因为Dictionary没有实现INotifyPropertyChanged或INotifyCollectionChanged
  2. 因为它不会像你想要的那样允许双向绑定.

我不确定它是否完全符合您的要求,但我会使用ObservableCollection一个自定义类.

我正在使用DataTemplate,以显示如何以两种方式对值进行绑定.

当然在这个实现中没有使用Key,所以你可以使用 ObservableCollection<int>

自定义类

public class MyCustomClass
{
    public string Key { get; set; }
    public int Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

设置ItemsSource

ObservableCollection<MyCustomClass> dict = new ObservableCollection<MyCustomClass>();
dict.Add(new MyCustomClass{Key = "test", Value = 1});
dict.Add(new MyCustomClass{ Key = "test2", Value = 2 });
listView.ItemsSource = dict;
Run Code Online (Sandbox Code Playgroud)

XAML

<Window.Resources>
    <DataTemplate x:Key="ValueTemplate">
        <TextBox Text="{Binding Value}" />
    </DataTemplate>
</Window.Resources>
<ListView Name="listView">
    <ListView.View>
        <GridView>
            <GridViewColumn CellTemplate="{StaticResource ValueTemplate}"/>
        </GridView>
    </ListView.View>
</ListView>
Run Code Online (Sandbox Code Playgroud)


And*_*ndy 6

这有点hacky,但我让它工作(假设我明白你想要的).

我首先创建了一个视图模型类:

class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        this.data.Add(1, "One");
        this.data.Add(2, "Two");
        this.data.Add(3, "Three");
    }

    Dictionary<int, string> data = new Dictionary<int, string>();
    public IDictionary<int, string> Data
    {
        get { return this.data; }
    }

    private KeyValuePair<int, string>? selectedKey = null;
    public KeyValuePair<int, string>? SelectedKey
    {
        get { return this.selectedKey; }
        set
        {
            this.selectedKey = value;
            this.OnPropertyChanged("SelectedKey");
            this.OnPropertyChanged("SelectedValue");
        }
    }

    public string SelectedValue
    {
        get
        {
            if(null == this.SelectedKey)
            {
                return string.Empty;
            }

            return this.data[this.SelectedKey.Value.Key];
        }
        set
        {
            this.data[this.SelectedKey.Value.Key] = value;
            this.OnPropertyChanged("SelectedValue");
        }
    }

    public event PropertyChangedEventHandler  PropertyChanged;
    private void OnPropertyChanged(string propName)
    {
        var eh = this.PropertyChanged;
        if(null != eh)
        {
            eh(this, new PropertyChangedEventArgs(propName));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在XAML中:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <ListBox x:Name="ItemsListBox" Grid.Row="0"
            ItemsSource="{Binding Path=Data}"
            DisplayMemberPath="Key"
            SelectedItem="{Binding Path=SelectedKey}">
        </ListBox>
        <TextBox Grid.Row="1"
            Text="{Binding Path=SelectedValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

Data属性的值绑定到ItemsSourceListBox.正如您在问题中所述,这导致使用实例KeyValuePair<int, string>作为后面的数据ListBox.我设置为DisplayMemberPath,Key以便键的值将用作每个项目的显示值ListBox.

当你发现,你不能只是使用ValueKeyValuePair作为数据TextBox,因为这是只读的.相反,TextBox它绑定到视图模型上的属性,该属性可以获取和设置当前所选键的值(通过将视图模型上的另一个属性的SelectedItem属性绑定来更新ListBox).我必须使这个属性可以为空(因为它KeyValuePair是一个结构),以便代码可以检测何时没有选择.

在我的测试应用程序中,这似乎导致对视图模型中TextBox传播的编辑Dictionary.

这或多或少是你想要的吗?它似乎应该更清洁,但我不确定是否有任何方法可以这样做.