【问题标题】:Why does WPF Binding update strings but not objects?为什么 WPF 绑定更新字符串而不更新对象?
【发布时间】:2009-06-17 09:32:07
【问题描述】:

在以下代码示例中,您可以将滑块从德语移动到英语,然后在运行时看到该文本块被翻译:

  • 只有绑定到 字符串 的 TextBlock 才会更新
  • 绑定到字典的 TextBlock 没有更新

View 似乎只是获取 Dictionary 对象一次,然后不再更新。我试过 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>

视图模型:

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");
            }

        }


    }
}

【问题讨论】:

  • 值得指出的是,这不是 WPF 本地化的好策略。为本地化字符串使用资源比将它们存储在字典中更为常见和有用。有一篇关于 CodeProject (codeproject.com/KB/WPF/WPFLocalize.aspx) 的文章展示了一种在运行时更改资源文件语言的好方法。

标签: c# wpf xaml binding


【解决方案1】:

你需要一个 ObservableList 的等价物,但需要一个字典。框架中默认没有,但是可以找到一篇描述一种编写方法的文章here.

您的代码现在无法正常工作的原因是您在 Translations Dictionary 的 setter 中触发了 NotifyPropertyChanged 事件,但是由于您的 FillTranslations 方法没有创建新 Dictionary,因此不会调用 setter并且事件不会触发。我想如果你创建一个新字典并分配它,你可以回避 ObservableDictionary 类,这反过来会触发事件并重新绑定整个列表,但从长远来看,保持相同的字典实例并通知控件更有效集合通过 Observable 模式发生了变化(在字典上实现 INotifyCollectionChanged)

【讨论】:

    【解决方案2】:

    您需要改用 ObservableCollection。

    当发生更改时必须通知 WPF 活页夹,您在设置字典属性时调用 OnPropertyChanged,但您还需要通知活页夹字典中的值已更改的一些原因。 ObservableCollection 将为您完成此操作。当从集合中添加/删除项目时,它会引发事件。

    【讨论】:

    • 我可以实现 Observable 集合而不是字典,但是由于我想在收集到例如TextBlock 而不是例如列表视图。
    • 我希望能够做到这一点:,原因是我的翻译中有 100 多个字符串对象,我不想让 100 个 ViewModelProperties 来读取它们,所以我需要一个可以使用键值访问的 ObservableCollection,例如一个“可观察字典”
    • 只需创建自己的 ObservableDictionary 类。实现 IDictionary INotifyCollectionChanged 和 INotifyPropertyChanged 的​​接口。实现添加、删除方法并在适当的时间调用集合/属性更改事件。在您的类内部使用私有普通 Dictionary 或 KeyedCollection 来存储数据。我认为 Martin 提供了一个很好的链接,说明如何开始这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-24
    • 2015-07-25
    • 1970-01-01
    相关资源
    最近更新 更多