2013-09-26 6 views
0

Я начал использовать 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 :(

Любая помощь будет высоко ценится:)

EDIT: О, и одна вещь, которую я забыл добавить - когда я попытался загрузить файл в конструкторе, он работал в текстовом поле и datagrid, так что это, вероятно, проблема с Bindings.

EDIT 2: Итак, вероятно, ошибка noob - я не знал, что каждый TabItem создает новый экземпляр моего ViewModel, а конструктор ViewModel создает новый экземпляр моего ObservableDictionary. Поэтому я переделал это примерно так:

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

И ЭТО РАБОТАЕТ! Однако это медленно, как черт ... Когда я меняю одно значение словаря, я должен ждать ~ 7 секунд, чтобы он обрабатывал все. Когда я загружаю файл, который меняет около 20 значений этого словаря, я должен ждать около минуты, чтобы обработать его. Ты знаешь почему?

ответ

0

Ваш 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.

+0

Коул вы объяснить еще? Я пробовал сделать что-то вроде этого: public TValue this [TKey key] { get {return (TValue) _keyedEntryCollection [key] .Value; } { DoSetEntry (ключ, значение); OnPropertyChanged (Binding.IndexerName); } } однако он не работает:/ – Pumar

+0

Я не знаю, что вы там делаете, но я привел вам пример в своем ответе. Прочтите внимательно. –

+0

Не могли бы вы посмотреть мое обновление, пожалуйста? – Pumar

0

Я думаю, что ваш обязательный источник в тыс Calss AdiDictionary сам не так этот код RaisePropertyChanged («AdiDictionary») не будет оповещать ваше связывание обновить TextProperty как ваш, за исключением

Смежные вопросы