可观察字典和更新绑定

时间:2013-09-26 09:24:24

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

我最近开始使用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 :(

任何帮助将不胜感激:)

编辑:哦,有一件事我忘了添加 - 当我尝试在构造函数中加载文件时,它在textbox和datagrid中工作,所以它可能与Bindings有关。

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

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

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

2 个答案:

答案 0 :(得分:2)

你的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事件。

答案 1 :(得分:0)

我认为你的绑定源是calss AdiDictionary本身并非如此 此代码RaisePropertyChanged(“AdiDictionary”)不会通知您的绑定更新 TextProperty作为你的