【问题标题】:Dependency property using view model values使用视图模型值的依赖属性
【发布时间】:2014-08-24 18:47:57
【问题描述】:

我在尝试实现包含视图模型和一些依赖属性的用户控件时遇到问题。

现在,想法是在 UC 上创建一个包含水印属性的文本框,该属性应该允许使用它的开发人员通过 xaml 将本地化字符串从资源文件传递给它。

鉴于 UC 必须处理一些信息,我需要为它创建一个视图模型。

我目前的情况如下:

在用户控件上,我有一个控件,其中包含一个名为“Watermark”的字符串属性,它的值绑定到我的 VM 水印属性:

<Grid x:Name="LayoutRoot" Background="Gray">    
    <controls:CustomTextBox Watermark="{Binding Path=WatermarkTextValue}"/>
</Grid>

视图模型如下所示:

private string watermarkText;
public string WatermarkTextValue
        {
            get
            {
                return watermarkText;
            }
            set
            {
                watermarkText = value;
                this.OnPropertyChanged(() => this.WatermarkTextValue);
            }
        }

后面的用户控制代码包含依赖属性,用于将视图模型的水印与资源文件条目绑定,并在构造函数中创建 VM 属性和依赖项之间的绑定:

public partial class SearchFilterUserControl : UserControl
    {
        public SearchFilterUserControl()
        {
            InitializeComponent();

            this.DataContext = new SearchFilterViewModel();
            var viewModelPropertyBinding = new Binding("WatermarkTextValue") { Mode = BindingMode.TwoWay, Source = this.DataContext };

            this.SetBinding(WatermarkTextProperty, viewModelPropertyBinding);
        }

        public string WatermarkText
        {
            get
            {
                return (string)this.GetValue(WatermarkTextProperty);
            }
            set
            {
                this.SetValue(WatermarkTextProperty, value);
            }
        }

        public static readonly DependencyProperty WatermarkTextProperty =
            DependencyProperty.Register("WatermarkText", typeof(string), typeof(SearchFilterUserControl), new PropertyMetadata(string.Empty));
    }

这里的主要问题是,从视图中使用 UC 时;我只能看到在 xaml 中硬编码的值,任何其他类型的绑定都不起作用,所以在这两行之外:

<userControls:SearchFilterUserControl WatermarkText="{Binding Path=SearchFilterUserControl_SearchWatermarkText, Source={StaticResource ResourceManagementClientResources}}"/>

<userControls:SearchFilterUserControl WatermarkText="Hardcoded text"/>

我看到一个空文本框和另一个带有“硬编码文本”水印的文本框!

【问题讨论】:

    标签: c# silverlight mvvm data-binding dependency-properties


    【解决方案1】:

    这里有一些问题,但让我们从这个开始:

    public SearchFilterUserControl()
    {
        InitializeComponent();
    
        this.DataContext = new SearchFilterViewModel();
    }
    

    执行此操作时,您正在更改控件的数据上下文,这将破坏控件用户的任何绑定。也就是说,有了这个:

    <controls:SearchFilterUserControl Watermark="{Binding Path=WatermarkTextValue}" />
    

    运行时现在将在作为其新数据上下文的“SearchFilterViewModel”中查找“WatermarkTextValue”。

    解决此问题的一种方法是将数据上下文应用到控件的子元素(通常是“LayoutRoot”或类似元素)。这样,外部 DataContext 将被保留。请注意,您必须在“OnApplyTemplate”覆盖中执行此操作——您不能在构造函数中执行此操作,因为尚未加载模板元素。像这样的:

    public SearchFilterUserControl()
    {
        InitializeComponent();
    
        this.DataContext = new SearchFilterViewModel();
    }
    
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        GetTemplateChild("LayoutRoot").DataContext = new SearchFilterViewModel();
    }
    

    第二个问题是,您似乎将“WatermarkTextValueProperty”作为绑定目标公开给控件的使用者,然后尝试将其重新设置为内部绑定到视图模型的目标。这显然行不通。

    我的建议是简单地放弃视图模型,并在模板绑定中使用IValueConverter 的组合,和/或依赖属性的“更改”事件来处理您需要的任何处理。这将不那么复杂。

    如果您坚持使用内部视图模型,那么您将需要找出一种方法将“外部”绑定(控件的使用者设置)与控件用于显示的“内部”绑定分开文本。

    【讨论】:

    • 感谢@McGarnagle 的回答,但我仍然有一个疑问:在我的代码中,传递文字和将资源绑定到 WatermarkText 有什么区别?我想不通。我知道我必须在这里遗漏一些简单的东西,但相信我,我离弄清楚这一点还很遥远:/
    • @NahuelI。哇,对不起,我现在看到我的回答很混乱。老实说,我发现很难跟随你在那里设置的流程,这有点时髦。如果没有更多细节,我认为我无法回答您的问题。也许您可以详细说明您需要的“处理” - 只是将水印文本转换为其他内容,还是什么?
    • @NahuelI。看起来您真正尝试的是使视图模型属性成为绑定的 target,而依赖属性是 source。理论上可行,除了视图模型属性不能是绑定目标,我认为这就是您尝试双向绑定的原因。但这混淆了一切。正如我上面提到的,我认为必须有更好的方法,使用 IValueConverter 和/或“依赖属性已更改”委托。
    • 你现在明白了,我正在尝试保存需要在 VM 上显示我的 DP 的值。值转换器在我想做的事情中不起作用,但我明天肯定会检查“dep.prop.changed”委托;一旦我尝试过,我会回复你的答案:)
    猜你喜欢
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    相关资源
    最近更新 更多