绑定导致StackOverflow [英] Binding causes StackOverflow

查看:62
本文介绍了绑定导致StackOverflow的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Im not sure what I am doing wrong here.

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

Lets say, I have two UserControls BoxAand 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆