我不确定我在这里做错了什么。

可以说,我有两个UserControls BoxABoxB。两者都有一个名为Text的DependencyProperty

BoxB包装具有常规TextBox的BoxA。

绑定应该像这样BoxB.Text BoxA.Text TextBox.Text

Xaml BoxA:

<UserControl x:Class="SandBoxWpf.BoxA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">

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

</UserControl>


Xaml BoxB:

<UserControl x:Class="SandBoxWpf.BoxB"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:SandBoxWpf"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">

    <local:BoxA Text="{Binding Text, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"></local:BoxA>

</UserControl>


BoxA和BoxB的代码隐藏

using System.Windows;
using System.Windows.Controls;

namespace SandBoxWpf
{
    /// <summary>
    /// Interaktionslogik für BoxA.xaml
    /// </summary>
    public partial class BoxX : UserControl
    {
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
                "Text",
                typeof(string),
                typeof(BoxX),
                new PropertyMetadata(default(string)));

        public string Text
        {
            get => (string) GetValue(TextProperty);
            set => SetValue(TextProperty, value);
        }

        public BoxX()
        {
            InitializeComponent();
        }
    }
}


主窗口

<Window x:Class="SandBoxWpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SandBoxWpf"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid>
        <local:BoxB Width="100" Height="20" Text="{Binding Title}"></local:BoxB>
    </Grid>
</Window>


一旦我在BoxB中输入内容,我就会得到StackoverflowException。
如果删除Mode = TwoWay或UpdateSourceTrigger,则StackOverflow消失了,但是绑定也不起作用。

最佳答案

如果要构建具有可绑定属性(即依赖项属性)的UserControl,则在任何情况下都不得显式设置UserControl的DataContext,无论它是控件实例还是任何私有视图模型。

如果那样做,像

<local:BoxB Text="{Binding Title}">


将不再起作用。该绑定在当前DataContext中的对象中期望有Title属性。 DataContext属性值通常是从UserControl的父元素继承的,例如窗户。但是,由于已经显式设置了DataContext,因此可以避免这种机制。

这与UserControls中的同名属性特别混淆。当你写

<local:BoxA Text="{Binding Text, ...}"/>


在UserControl BoxB中,您的期望是Binding source属性为BoxB.Text。实际上,它是BoxA.Text,因为BoxA的DataContext是BoxA实例。



所以删除任何

DataContext="{Binding RelativeSource={RelativeSource Self}}"


行,并使用RelativeSource在UserControl的XAML中编写绑定,如下所示:

<TextBox Text="{Binding Text, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay},
                RelativeSource={RelativeSource AncestorType=UserControl}"/>

<local:BoxA Text="{Binding Text, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay},
                   RelativeSource={RelativeSource AncestorType=UserControl}"/>

关于c# - 绑定(bind)导致StackOverflow,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48707331/

10-09 16:58