【问题标题】:When creating user controls, should one use data binding between view & code-behind? [duplicate]创建用户控件时,是否应该在视图和代码隐藏之间使用数据绑定? [复制]
【发布时间】:2020-02-13 19:34:43
【问题描述】:

我和一个队友正在讨论在 WPF 中创建用户控件的不同方法。具体来说,讨论的背景是从头开始构建的数字向上/向下用户控件。它由一个用于标题的标签、一个用于值的文本框、一个用于单位的标签和 2 个用于向上/向下操作的按钮组成。最终目标是绑定到此用户控件从屏幕视图模型中公开的属性。

用户控件的TextBox xaml声明如下:

<TextBox x:Name="Textbox" Text="{Binding TextboxValue, FallbackValue=0}" Width="100" Height="40" TextAlignment="Left" FontSize="28" VerticalAlignment="Center"  BorderBrush="Black" BorderThickness="2"/>

TextBoxes Text 属性绑定到用户控件视图的代码隐藏。代码隐藏相关部分的片段如下所示。

public static readonly DependencyProperty TextboxValueProperty = DependencyProperty.Register("TextboxValue",
         typeof(double), typeof(IncrementDecrementTextbox), new PropertyMetadata(12.0d, new PropertyChangedCallback(OnTextboxValueChanged)));

public IncrementDecrementTextbox()
{
    InitializeComponent();
    this.DataContext = this;
}

public double TextboxValue
{
    get
    {
        return (double)GetValue(TextboxValueProperty);
    }
    set
    {
        SetValue(TextboxValueProperty, value);
        NotifyTextboxValueUpdated();
    }
}

private static void OnTextboxValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    IncrementDecrementTextbox control = d as IncrementDecrementTextbox;
    control.OnTextboxValueChanged(e);
}

private void OnTextboxValueChanged(DependencyPropertyChangedEventArgs e)
{
    TextboxValue = Convert.ToDouble(e.NewValue);
}

public event EventHandler TextboxValueUpdated;

private void NotifyTextboxValueUpdated()
{
    TextboxValueUpdated?.Invoke(this, EventArgs.Empty);
}

这个用户控件的实现让我感到困惑。我不明白为什么在视图和它的代码隐藏部分之间使用数据绑定。我认为,由于代码隐藏和相应的 xaml 视图本质上是一回事,因此人们希望通过设置元素的 x:Name 属性直接从后面的代码访问在 xaml 中声明的元素。但是,我可能会遗漏一些东西。

在创建用户控件时,视图和代码隐藏之间的绑定是一种标准做法吗?如果没有,有更好的方法吗?

谢谢!

【问题讨论】:

  • 在后面的代码中创建依赖属性,然后绑定到视图上。然后你可以绑定到用户控件属性,如果你愿意的话。
  • 首先:您应该永远将您的UserControl.DataContext 属性设置为thisusing 控件的代码需要能够设置它,以便它们可以将其视图模型属性绑定到控件的属性。除此之外,如何传播值取决于您,但一种常见的策略是使用绑定来指定带有RelativeAncestor 标记的源。您也可以按名称指定源,但这可能会再次干扰客户端代码(即,如果您的客户端代码也想设置名称)。有关该主题的广泛讨论,请参阅标记的重复项。
  • 昨晚我阅读了关于在 Pro WPF 4.5 In C# 中创建自定义用户控件的第 18 章,这几乎回答了我的任何问题。绝对不想将 DataContext 设置为此。使用绑定在视图和代码隐藏之间进行绑定是完全没问题的,并且对于使用用户控件的绑定工作来说实际上是必要的。在控件视图中使用 RelativeAncestor 标记是我在那一章中看到的一个建议。

标签: c# wpf xaml data-binding code-behind


【解决方案1】:

我认为你可以这样做。

public UserControl1()
{
    InitializeComponent();
}



public string TextValue
{
    get { return (string)GetValue(TextValueProperty); }
    set { SetValue(TextValueProperty, value); }
}

// Using a DependencyProperty as the backing store for TextValue.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty TextValueProperty =
    DependencyProperty.RegisterAttached("TextValue", typeof(string), typeof(UserControl1), new PropertyMetadata(null, OnTextValueChange));

private static void OnTextValueChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    UserControl1 userControl = (UserControl1)d;
    string value = (string)e.NewValue;
    if (userControl == null || value == null)
        return;
    userControl.textvalue.Text = value;
}

您不需要将用户控件绑定到其背后的代码。

【讨论】:

  • 确实不用数据绑定也能完成目标。但这样做很愚蠢。我还要指出你建议的实现是有缺陷的:d 永远不应该是null(这样检查是没有意义的)并且将Text 值设置为null 并不违法(这样检查就会禁用,否则-法律行为)。
  • @PeterDuniho 对不起,我在这条评论中学到了一些东西。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
  • 1970-01-01
  • 2010-11-03
  • 2019-01-03
  • 2010-11-10
相关资源
最近更新 更多