【问题标题】:Observable Dictionary and updating bindings可观察字典和更新绑定
【发布时间】:2013-09-26 09:24:23
【问题描述】:

我最近开始使用 WPF,但绑定有两个问题..

我正在使用这个ObservableDictionary
当我将它绑定到 TextBox 时,它可以完美运行,但 DataGrid 有问题:

我的按钮绑定:

Text="{Binding AdiDictionary[AssetName], Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}

我的 DataGrid 绑定:

<DataGrid Grid.Row="1" Margin="5" Name="AdiDataGrid" Background="Transparent" IsReadOnly="True" ItemsSource="{Binding AdiDictionary, Mode=OneWay}" AutoGenerateColumns="False">
   <DataGrid.Columns>
      <DataGridTextColumn Header="Meta-Data Name" Binding="{Binding Path=Key}" />
      <DataGridTextColumn Header="Meta-Data Attribute" Binding="{Binding Path=Value}" Width="1*"/>
   </DataGrid.Columns>
</DataGrid>

据我了解,它是这样工作的,因为 ObservableDictionary.Value 没有实现 INotifyPropertyChanged,但是我尝试了多种解决方案,但我无法使其工作:(

第二件事:用户应该有可能加载设置文件。

void LoadAdiSettingsFileExecute()
{
  var loadDialog = new Microsoft.Win32.OpenFileDialog();

  loadDialog.DefaultExt = ".txt";
  loadDialog.Filter = "Txt files (*.txt)|*.txt";

  if ((bool) loadDialog.ShowDialog())
  {
    var textFile = AdiSettingsFile.ReadingSettingsFileToDictionary(loadDialog.FileName);
    foreach (KeyValuePair<string, string> x in textFile)
    {
      AdiDictionary[x.Key] = x.Value;
    }
    RaisePropertyChanged("AdiDictionary");
  }
}

bool CanLoadAdiSettingsFileExecute()
{
  return true;
}

public ICommand LoadAdiSettingsFile {get {return new RelayCommand(LoadAdiSettingsFileExecute, CanLoadAdiSettingsFileExecute);}}

不幸的是,虽然它可以工作 - 当我调试以查看 AdiDictionary 值时,它们都在那里,但是它不会更新任何 TextBoxes 或 DataGrid:(

任何帮助将不胜感激:)

编辑:哦,我忘了添加一件事 - 当我尝试在构造函数中加载文件时,它在文本框和数据网格中工作,所以它可能是绑定的问题。

编辑 2: 好的,所以可能是新手错误 - 我不知道每个 TabItem 都在创建我的 ViewModel 的新实例,而 ViewModel 构造函数正在创建我的 ObservableDictionary 的新实例。所以我把它改成这样:

private static ObservableDictionary<string, string> _adiDictionary = new ObservableDictionary<string, string>(StringComparer.OrdinalIgnoreCase);

而且它有效!但是它的速度很慢。当我更改字典的一个值时,我必须等待约 7 秒才能处理所有内容。当我加载一个更改该字典大约 20 个值的文件时,我必须等待大约一分钟才能处理它。你知道为什么吗?

【问题讨论】:

    标签: c# wpf dictionary datagrid .net-4.5


    【解决方案1】:

    你的 ObservableDictionary.Value 应该实现 INotifyPropertyChanged 然后一切都会神奇地工作。

    这是后面的代码:

    public partial class MainWindow : Window
    {
        public MyDictionary<string, string> Dic
        {
            get;
            set;
        }
    
        public MainWindow()
        {
            InitializeComponent();
            this.Dic = new MyDictionary<string, string>();
            this.DataContext = this;
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.Dic["0"] = new Random().Next().ToString();
        }
    }
    
    public class MyDictionary<TKey, TValue> : Dictionary<TKey, TValue>, INotifyPropertyChanged
    {
        public TValue this[TKey index]
        {
            get
            {
                return base[index];
            }
    
            set
            {
                base[index] = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs(Binding.IndexerName));
                }
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    }
    

    这就是我的 XAML 中的内容:

    <StackPanel>
        <TextBox Text="{Binding Path=Dic[0], Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <Button Content="click me" Click="Button_Click"/>
    </StackPanel>
    

    在类中实现 INotifyPropertyChanged 很容易。只需触发 PropertyChanged 事件。

    【讨论】:

    • 你能再解释一下吗?我试过做这样的事情: public TValue this[TKey key] { get { return (TValue)_keyedEntryCollection[key].Value; } set { DoSetEntry(key, value); OnPropertyChanged(Binding.IndexerName); } } 但是它仍然不起作用:/
    • 我不知道你在那里做什么,但我在回答中给了你一个例子。请仔细阅读。
    • 什么是慢得要命?你必须给我更多信息什么是慢的,你到底想做什么?您在上面的代码中向我们展示了您正在使用 DataGrid,但现在突然之间您正在谈论 TabItems。我不知道 ObservableDictionary 是什么,我还没有下载该代码。我向您提供了我的代码。我的代码示例对我来说并不慢。正如您在我的示例中看到的,我刚刚创建了一个派生自原始 Dictionary 的类,并且在设置值时触发了 PropertyChanged。准确告诉我们您在做什么,或在 github.com 上上传您的完整代码。
    • 我认为它在初始化this.Dic = new MyDictionary&lt;string, string&gt;(){ {"1", "First"} }; 的情况下不起作用,在初始化期间要添加什么通知? ObservableDictionary.cs
    【解决方案2】:

    我认为您的绑定源在 ths 类 AdiDictionary 中,而不是它本身 此代码 RaisePropertyChanged("AdiDictionary") 不会通知您的绑定更新 TextProperty 作为您的除外

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-23
      • 2012-11-02
      • 2012-05-01
      • 1970-01-01
      • 2017-11-25
      • 2014-06-23
      相关资源
      最近更新 更多