【问题标题】:What is the proper way to create dependency properties in user controls that allow two way bindings在允许双向绑定的用户控件中创建依赖属性的正确方法是什么
【发布时间】:2016-03-04 07:27:18
【问题描述】:

我说得对,因为我看到的所有例子似乎都相互矛盾,或者在某些方面存在不足。我需要能够从 XAML 将类对象绑定到我的 DP 或在 cb 中以编程方式设置它:

<local:MyControl MyDP="{Binding MyObject}"/>

MyControl mycontrol = new MyControl(){MyDP = MyObject};

然后在控件内,通过两种方式将元素绑定到绑定对象的属性:

<TextBox text="{Binding MyDP.text, ElementName=MyControl}"/>

我认为这是非常标准的东西,但是我看到尝试编写示例的人缺乏凝聚力,这让我不这么认为。

【问题讨论】:

  • 我就是这样做的,在用户控件中指定你的 DPs。
  • 你的MyObject实现INotifyPropertChanged了吗?
  • 是的,出于其他原因。

标签: c# wpf


【解决方案1】:

这就是我的做法:

假设一个父控件包含一个状态栏(用户控件),它的标记是这样的:

    <ContentControl x:Name="XFoot" Grid.Row="1" Grid.ColumnSpan="3" >
        <UserControls:UCStatusBar />
    </ContentControl>

现在在名为 UserControl 的状态栏中,它的依赖属性如下所示:

   public StatusUpdate CurrentStatus
        {
            get { return (StatusUpdate)GetValue(CurrentStatusProperty); }
            set { SetValue(CurrentStatusProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CurrentStatus.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CurrentStatusProperty =
            DependencyProperty.Register("CurrentStatus", typeof(StatusUpdate), typeof(UCStatusBar), 
                new PropertyMetadata(
                        new StatusUpdate() {  ErrorMessage="", IsIndeterminate=false, Status="Ready"}
                        )
                );

状态更新看起来像这样,它只是状态栏中显示的三个属性的容器。

 public class StatusUpdate
    {
       public StatusUpdate()
       {
           Status = "";
           ErrorMessage = "";
           IsIndeterminate = true;
       }
        public string Status { get; set; }
        public string ErrorMessage { get; set; }
        public bool IsIndeterminate { get; set; }
    }
}

任何人都可以通过访问状态栏的 CurrentStatus 属性来更新状态栏。注意要进行双向绑定,这是在 XAML 中完成的...在绑定指令中,只需按空格键,属性窗口就会显示绑定模式。选择两种方式。

PS:在 Visual Studio 中,当您第一次创建 DP 时,只需键入 propdp 并按下 tab 按钮,整个 DP 结构就会自动为您插入。因此,DP 很容易实现。

DP 如何双向工作?

如果您使用 XAML 绑定,您只需通过 MODE 属性告诉它这是两种方式。这意味着当用户更改值时,GUI 更改将更新属性。

<TextBox Text="{Binding Path=ThePropertyName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

注意 Mode 值和 UpdateSourceTrigger 说,不想改变焦点,立即更新。

等一下,我绑定并进行更改时什么都没有发生!

绑定工作需要三件事 1) DataContext 必须在代码中设置或作为 XAML 中的静态资源 2) 属性名称的路径名必须与 CLR 属性名称完全相同 3) 必须有属性中的内容。

我可以从其他地方触发事件来更新属性吗? 当然...第一步是在 UserControl 中设置静态事件处理程序,如下所示:

public static EventHandler<string> NewData;

然后在 CTOR 中像这样连接起来:

NewData+=OnNewData;

那么事件处理程序如下所示:

 private void OnNewData(object sender, string data){
   //setting this string property notifies WPF to update the GUI
   ThePropertyName = data;
  }

其他代码是这样做的……

MyUserControl.OnNewData(this, "Now is the time for all good men to...");

【讨论】:

  • 如果 DP 是通过构造函数或属性直接设置的,如何引发事件以刷新控件内部绑定?
  • 我的 userControl 需要实现 INotify 还是我的类对象?在 CB 中设置属性似乎对绑定到对象属性的控件元素没有影响。
  • 用户控制不需要 INPC,因为 DP 做同样的事情。我将更新代码以讨论更新的方式和时间。
  • 知道为什么 DP 不允许我将其用作 setter 属性吗?它在 XAML 中抛出错误,说 setter 属性不是依赖属性。
  • 在 XAML 中,您不会绑定到 DP,而是绑定到使用 DP 的 CLR Wrapper 属性。
猜你喜欢
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 2018-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多