我不确定我在这里做错了什么。
比方说,我有两个 UserControls BoxA
和 BoxB
。两者都有一个名为 Text
BoxB 包装了具有常规 TextBox 的 BoxA。
绑定(bind)应该像这样 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 就会消失,但绑定(bind)也不起作用。
最佳答案
如果您正在构建具有可绑定(bind)属性(即依赖属性)的 UserControl,则您必须在任何情况下都必须显式设置 UserControl 的 DataContext,无论是对控件实例还是对任何私有(private) View 模型。
如果你这样做,一个类似于
的绑定(bind)<local:BoxB Text="{Binding Title}">
将不再起作用。该 Binding 需要当前 DataContext 中的对象具有 Title 属性。 DataContext 属性值通常继承自 UserControl 的父元素,例如 window 。但是,由于您已显式设置 DataContext,因此可以避免这种机制。
这与 UserControls 中的同名属性尤其令人困惑。当你写的时候
<local:BoxA Text="{Binding Text, ...}"/>
在 UserControl BoxB 中,您期望绑定(bind)源属性为 BoxB.Text
。事实上它是 BoxA.Text
,因为 BoxA 的 DataContext 是 BoxA 实例。
所以删除任何
DataContext="{Binding RelativeSource={RelativeSource Self}}"
行并使用RelativeSource 在 UserControl 的 XAML 中编写绑定(bind),如下所示:
<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/