绑定导致StackOverflow [英] Binding causes StackOverflow
问题描述
我不确定我在这里做错了什么.
Im not sure what I am doing wrong here.
可以说,我有两个UserControls BoxA
和BoxB
.两者都有一个名为Text
Lets say, I have two UserControls BoxA
and BoxB
. Both have a DependencyProperty called Text
BoxB包装了具有常规TextBox的BoxA.
BoxB wraps BoxA which has a regular TextBox.
绑定应该像这样BoxB.Text< => BoxA.Text< => TextBox.Text
Binding should work like this 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();
}
}
}
MainWindow
<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消失了,但是绑定也不起作用.
As soon as I type something into the BoxB i get a StackoverflowException. If I remove the Mode=TwoWay or the UpdateSourceTrigger the StackOverflow is gone, but the binding doesnt work either.
推荐答案
如果要构建具有可绑定属性(即依赖项属性)的UserControl,则必须在任何情况下都不得显式设置UserControl的DataContext ,它是控件实例还是任何私有视图模型.
If you are building a UserControl with bindable properties (i.e. dependency properties), you must under no circumstances explicitly set the UserControl's DataContext, be it to the control instance or to any private view model.
如果这样做,
<local:BoxB Text="{Binding Title}">
将不再起作用.该绑定在当前DataContext中的对象中期望有Title属性. DataContext属性值通常是从UserControl的父元素继承的,例如窗户.但是,由于已经显式设置了DataContext,因此可以避免这种机制.
will no longer work. That Binding expects a Title property in the object in the current DataContext. The DataContext property value is usually inherited from the parent element of the UserControl, e.g. the Window. However, since you've explicitly set the DataContext, this mechanism is avoided.
这与UserControls中的同名属性特别混淆.当你写
This becomes particularly confusing with equally named properties in UserControls. When you write
<local:BoxA Text="{Binding Text, ...}"/>
在UserControl BoxB中,您的期望是Binding source属性为BoxB.Text
.实际上,它是BoxA.Text
,因为BoxA的DataContext是BoxA实例.
in UserControl BoxB, your expectation is that the Binding source property is BoxB.Text
. In fact it is BoxA.Text
, because BoxA's DataContext is the BoxA instance.
因此删除所有
DataContext="{Binding RelativeSource={RelativeSource Self}}"
如下所示,并使用RelativeSource在UserControl的XAML中编写绑定:
lines and write the Bindings in the UserControl's XAML with RelativeSource like this:
<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}"/>
这篇关于绑定导致StackOverflow的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!