2009-06-17 1 views
1

В следующем примере кода, вы можете переместить ползунок с немецкого на английский и посмотреть, что текстовый блок переводятся во время выполнения, однако:Почему WPF Binding обновляет строки, но не объекты?

  • только TextBlock привязан к строке получает обновленный
  • TextBlock привязан к словарьне получить обновленный

кажется, что View просто получает Di объект ctionary один раз, а затем больше не обновляется. Я пробовал Mode = TwoWay, но это не влияет.

Что мне нужно для того, чтобы элементы, связанные с объектами ? получить обновление через привязку?

Вид:

<Window x:Class="TestObjectUpdate234.Views.MainView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:c="clr-namespace:TestObjectUpdate234.Commands" 
    Title="Main Window" Height="400" Width="800"> 
    <StackPanel Margin="10"> 

     <TextBlock Text="{Binding TranslationEdit}" /> 
     <TextBlock Text="{Binding Translations[add], Mode=TwoWay}" /> 

     <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Margin="0 20 0 0"> 
      <TextBlock Text="English" Margin="0 0 5 0"/> 
      <Slider Name="TheLanguageIndexSlider" 

       Minimum="0" 
       Maximum="1" 
       IsSnapToTickEnabled="True" 
       Width="100" 
       Margin="5" 
       Value="{Binding LanguageIndex}" 
       HorizontalAlignment="Left"/> 
      <TextBlock Text="German" Margin="5 0 0 0"/> 
     </StackPanel> 

    </StackPanel> 
</Window> 

ViewModel:

using System.Collections.Generic; 

namespace TestObjectUpdate234.ViewModels 
{ 
    public class MainViewModel : ViewModelBase 
    { 

     #region ViewModelProperty: TranslationEdit 
     private string _translationEdit; 
     public string TranslationEdit 
     { 
      get 
      { 
       return _translationEdit; 
      } 

      set 
      { 
       _translationEdit = value; 
       OnPropertyChanged("TranslationEdit"); 
      } 
     } 
     #endregion 

     #region ViewModelProperty: Translations 
     private Dictionary<string, string> _translations = new Dictionary<string, string>(); 
     public Dictionary<string, string> Translations 
     { 
      get 
      { 
       return _translations; 
      } 

      set 
      { 
       _translations = value; 
       OnPropertyChanged("Translations"); 
      } 
     } 
     #endregion 

     #region ViewModelProperty: LanguageIndex 
     private int _languageIndex; 
     public int LanguageIndex 
     { 
      get 
      { 
       return _languageIndex; 
      } 

      set 
      { 
       _languageIndex = value; 
       OnPropertyChanged("LanguageIndex"); 
       FillTranslations(); 
      } 
     } 
     #endregion 

     public MainViewModel() 
     { 
      _languageIndex = 0; //english 
      FillTranslations(); 

     } 

     private void FillTranslations() 
     { 
      if (_languageIndex == 0) 
      { 
       TranslationEdit = "Edit"; 

       Translations.Clear(); 
       Translations.Add("add", "Add"); 
      } 
      else 
      { 
       TranslationEdit = "Bearbeiten"; 

       Translations.Clear(); 
       Translations.Add("add", "Hinzufügen"); 
      } 

     } 


    } 
} 
+0

Возможно, стоит отметить, что это не очень хорошая стратегия для локализации WPF. Это гораздо более распространено и полезно использовать ресурсы для ваших локализованных строк, а не хранить их в словаре. Существует статья о CodeProject (http://www.codeproject.com/KB/WPF/WPFLocalize.aspx), которая показывает хороший способ изменить язык файла ресурсов во время выполнения. –

ответ

1

Вы должны использовать ObservableCollection <> вместо этого.

Взаимодействие WPF должно быть уведомлено о произошедшем изменении, вы вызываете OnPropertyChanged, когда свойство словаря задано, но вам также необходимо указать, почему уведомление об уведомлении об изменении значений внутри словаря. ObservableCollection <> сделает это за вас. Он вызывает события, когда элементы добавляются/удаляются из коллекции.

+0

Я мог бы реализовать Observable collection вместо словаря, но как я могу вытащить объект из наблюдаемой коллекции с помощью ключа, как в «Binding Translations [add]», так как я хочу связать объекты в коллекции, например. TextBlock вместо, например, Посмотреть список. –

+0

Я хочу, чтобы это можно было сделать: , причина в том, что у меня есть 100 строк в моем объекте Translation, и я не хочу, чтобы 100s ViewModelProperties читали их все, поэтому мне нужен ObservableCollection, с которым я могу получить доступ с ключом значения, например, «ObservableDictionary» –

+0

Просто создайте свой собственный класс ObservableDictionary <>. Внедрите интерфейсы для IDictionary <<> INotifyCollectionChanged и INotifyPropertyChanged. Внедрите методы добавления, удаления и вызовите события, связанные с изменением коллекции/свойства, в соответствующие моменты времени. Словарь <> или KeyedCollection <> внутри вашего класса для хранения данных. Я думаю, что Мартин дал хорошую ссылку о том, как начать работу над этим. –

2

Вам нужен эквивалент ObservableList, но для словаря. По умолчанию в Framework нет ни одной статьи, но можно найти статью, описывающую один способ ее написания. here.

Причина, по которой ваш код не работает, поскольку он стоит сейчас, заключается в том, что вы запускаете событие NotifyPropertyChanged в сеттер словаря переводов, но так как ваш метод FillTranslations не создает новый словарь, сеттер не вызывается и событие не срабатывает. Я полагаю, вы могли бы обойти класс ObservableDictionary, если бы вы создали новый словарь и назначили его, что, в свою очередь, вызовет событие и перепроверет весь список, но в конечном итоге более эффективно поддерживать один и тот же экземпляр словаря и уведомлять элемент управления, который коллекция изменилась через шаблон Observable (внедрение INotifyCollectionChanged в словаре)

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

  • Нет связанных вопросов^_^