【问题标题】:How to use TwoWay binding from within a UserControl?如何在 UserControl 中使用 TwoWay 绑定?
【发布时间】:2012-05-01 20:59:37
【问题描述】:

我有我自己的 UserControl,LabeledTextBox,它是 Label 和..well,TextBox 的组合。此控件有两个属性:Caption 将绑定到 Label 的标题,Value 将绑定到 TextBoxText

代码:

public class LabeledTextBox : Control
{
    static LabeledTextBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(LabeledTextBox), new FrameworkPropertyMetadata(typeof(LabeledTextBox)));
    }

    public string Caption
    {
        get { return (string)GetValue(CaptionProperty); }
        set { SetValue(CaptionProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Caption.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CaptionProperty =
        DependencyProperty.Register("Caption", typeof(string), typeof(LabeledTextBox), new UIPropertyMetadata(""));


    public string Value
    {
        get { return (string)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(string), typeof(LabeledTextBox), new UIPropertyMetadata(""));


}

XAML:

<Style TargetType="{x:Type local:LabeledTextBox}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:LabeledTextBox}">
                <Grid>
                    <Grid>

                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>

                    <Label Grid.Row="0" Content="{TemplateBinding Caption}" />
                    <TextBox  Name="Box" Margin="3,0,3,3" Grid.Row="1" Text="{Binding Value, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />

                    </Grid>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

用法:

<uc:LabeledTextBox Caption="Code:" Value="{Binding ExpenseCode}"  />

最初我以为我在这里找到了答案:WPF TemplateBinding vs RelativeSource TemplatedParent

这详细说明了TemplateBindingRelativeSource TemplatedParent 之间的区别。我已经相应地更改了我的代码,但仍然感觉我错过了一步。 OneWay 绑定确实有效,我的文本框绑定到 Value 属性,但更改不会注册。

如何让它工作?

【问题讨论】:

  • 您是否尝试过让您的 Value 依赖属性 TwoWay 也一样?还是 TextBox 没有写入您的 Value dp 的问题?
  • LabeledTextBox.Value 没有改变还是数据对象中的ExpenseCode?您可以将PropertyChangedCallback 添加到Value 依赖属性以查看它是否被调用。
  • @dowhilefor: 这不是 XAML 中的 Mode=TwoWay 的用途吗? @Clemens:我最初确实有那个回调,它确实被调用了。在那个回调中,我设置了文本框的值。我是否需要明确地让数据从 DP 中返回? @Ricibob:谢谢,但似乎并非如此。
  • @diggingforfire 看起来一切正常,在您的控件中使用双向绑定。正如@akanksha 所回答的那样,TwoWay 只是在 ExpenseCode 绑定中丢失了。
  • @diggingforfire 您的双向模式是从 TextBox UserControl 设置的...但是您的用户控件公开了 value 属性,该属性使用单向绑定,因此您拥有 Usedcontrol -> UserControl TextBox .请记住,有 2 个绑定处于活动状态,即模板绑定和“用户”绑定。

标签: wpf data-binding user-controls controltemplate


【解决方案1】:

在此处更改模式。

<uc:LabeledTextBox Caption="Code:" Value="{Binding ExpenseCode,Mode=TwoWay}"  /> 

它在我的最后工作

【讨论】:

  • 我在声明的样式中尝试了所有可能的模式组合。 @dowhile 是对的,感谢您的解释:)
  • 我还不是 WPF 专家,但这是一个好方法 :)
【解决方案2】:

以防万一有人遇到这个问题:

另一种方法(可能更优雅)是以某种方式声明用户控件的依赖属性,使其默认为双向绑定(例如,框架 TextBox 默认情况下)。

这可以实现如下(取自this Stackoverflow question的回答):

    public DependencyProperty SomeProperty =
        DependencyProperty.Register("Some", typeof(bool), typeof(Window1),
            new FrameworkPropertyMetadata(default(bool),
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

这里的关键是使用FrameworkPropertyMetadata

【讨论】:

    猜你喜欢
    • 2013-05-07
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 2010-12-26
    • 1970-01-01
    相关资源
    最近更新 更多