c#uwp中的双绑定

c#uwp中的双绑定,c#,xaml,binding,uwp,C#,Xaml,Binding,Uwp,我有个问题。我为我的应用程序创建了两个控件:底部菜单控件和结果框。ResultBox包含在BottomMenu中,因此顺序如下:Page->BottomMenu->ResultBox。我在ResultBox中创建了一个名为Result of type string的依赖项属性 public ResultBox() { this.InitializeComponent(); this.DataContext = this; } //

我有个问题。我为我的应用程序创建了两个控件:底部菜单控件和结果框。ResultBox包含在BottomMenu中,因此顺序如下:Page->BottomMenu->ResultBox。我在ResultBox中创建了一个名为Result of type string的依赖项属性

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

    /// <summary>
    /// Property used to store the result of the calculation
    /// </summary>
    public static readonly DependencyProperty ResultProperty = DependencyProperty.Register(
        "Result",
        typeof(string),
        typeof(ResultBox),
        new PropertyMetadata(null)
        );

    /// <summary>
    /// String holding the text assigned to the Result
    /// </summary>
    public string Result
    {
        get => (string)GetValue(ResultProperty);
        set => SetValue(ResultProperty, value);
    }
public ResultBox()
{
this.InitializeComponent();
this.DataContext=this;
}
/// 
///用于存储计算结果的属性
/// 
公共静态只读DependencyProperty结果属性=DependencyProperty.Register(
“结果”,
类型(字符串),
类型(结果框),
新属性元数据(空)
);
/// 
///保存指定给结果的文本的字符串
/// 
公共字符串结果
{
get=>(字符串)GetValue(ResultProperty);
set=>SetValue(ResultProperty,value);
}
其约束力如下:

<TextBlock  Style="{StaticResource DefaultTextBlockStyle}"
                        Text="{Binding Result}"/>

然后,我在底部菜单中创建了相同的依赖项属性,这样就可以直接从页面进行设置

    public BottomMenu()
    {
        this.InitializeComponent();
        this.DataContext = this;
    }
    /// <summary>
    /// Property used to store the result of the calculation
    /// </summary>
    public static readonly DependencyProperty ResultProperty = DependencyProperty.Register(
        "Result",
        typeof(string),
        typeof(BottomMenu),
        new PropertyMetadata(null)
        );

    /// <summary>
    /// String holding the text assigned to the Result
    /// </summary>
    public string Result
    {
        get => (string)GetValue(ResultProperty);
        set => SetValue(ResultProperty, value);
    }
public-BottomMenu()
{
this.InitializeComponent();
this.DataContext=this;
}
/// 
///用于存储计算结果的属性
/// 
公共静态只读DependencyProperty结果属性=DependencyProperty.Register(
“结果”,
类型(字符串),
类型(底部菜单),
新属性元数据(空)
);
/// 
///保存指定给结果的文本的字符串
/// 
公共字符串结果
{
get=>(字符串)GetValue(ResultProperty);
set=>SetValue(ResultProperty,value);
}
和约束:

<local:ResultBox Grid.Row="1" Margin="0 0 0 10"
                        Result="{Binding Result}"
                        />

不幸的是,只有当我在ResultBox声明中直接输入文本时,才会显示文本。当我进行双重绑定并将其输入页面时

<local:BottomMenu Grid.Row="2"                              
                            Result="13"/>

它不起作用。我正在学习绑定,我想知道我哪里做错了,或者这是否是做这件事的正确方法


编辑:ResultBox中的绑定不应包含源代码,现已修复。

您几乎不应该使用
this.DataContext=this
;内部控制。始终在顶层页面定义
DataContext
,并让它一路向下流到每个控件

因此,首先删除

this.DataContext = this;
您已正确定义依赖项属性
Result
。要将
TextBlock
Text
绑定到它,您可以命名控件并使用
ElementName
绑定,或者更有效地使用
x:bind
,如下所示

<TextBlock Style="{StaticResource DefaultTextBlockStyle}" Text="{x:Bind Result, Mode=OneWay}"/>

这也一样

<local:ResultBox Grid.Row="1" Margin="0 0 0 10" Result="{x:Bind Result, Mode=OneWay}" />


希望这有帮助。

这里,而不是设置
this.DataContext=this
,我们应该使用
(this.Content作为FrameworkElement)如下所示:

public BottomMenu()
{
    this.InitializeComponent();
    (this.Content as FrameworkElement).DataContext = this;
}
在上面的代码中,我们没有设置用户控件的数据上下文,而是设置用户控件中第一个子控件的数据上下文。在此之后,
BottomMenu
中的
ResultBox
可以从
BottomMenu
继承数据上下文,并且可以正确设置其
Result
属性。有关更多信息,请参阅杰瑞·尼克松的博客:
.

注意这是可行的,但这不是UWP中推荐的方法。这样设置
DataContext
会中断数据流,并会产生副作用。更不用说在性能方面,它比使用
x:Bind
更糟糕。如果有兴趣,可以从中查看关于
DataContext=this
的讨论。@JustinXL我同意我们不应该在
UserControl
上设置
DataContext=this
。这就是为什么我们使用
(this.Content as FrameworkElement)设置用户控件中第一个子控件的数据上下文。这将解决上述问题中的数据上下文继承问题。这可能不是UWP中的最佳解决方案,但我认为在UserControl内部使用绑定时,这仍然是一种替代方法。这基本上是一样的,对吗?如果将其设置为
this
,则会转到
this.Content
。这绝对是一个选择,只是不是一个好的选择。通常,即使没有
x:Bind
,也应该使用
ElementName
绑定来代替此模式:与
ElementName
one相比,这个解决方案可能有点棘手,也很难理解。这里的关键点是我们需要
UserControl
级别的数据上下文继承,因此我们不应该设置用户控件的数据上下文。但是,在用户控件内部,我们总是关注自定义DP(或
UserControl
的一些现有属性),而不是外部的数据上下文,因此我们可以使用第一个子级(通常是容器)的数据上下文来执行绑定。我认为这也是一个出色的解决方案,它比使用
ElementName
还不错。
public ResultBox()
{
    this.InitializeComponent();
    (this.Content as FrameworkElement).DataContext = this; 
}