UserControl InitializeComponents()方法设置Content属性,但不触发绑定更新

时间:2013-08-05 09:19:01

标签: xaml windows-8 windows-runtime winrt-xaml windows-8.1

例如,有一个来自 UserControl MyUserControlBase 类,并且在其构造函数中有内容<的绑定集合/ strong>依赖属性。

MyUserControlBase.cs

namespace BindingBeforeInitComp
{
    using System.Diagnostics;

    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Data;

    public class MyUserControlBase : UserControl
    {
        public static readonly DependencyProperty MyContentProperty = DependencyProperty.Register("MyContent",
            typeof(object),
            typeof(MyUserControl),
            new PropertyMetadata(null, MyContentChangedCallback));

        public MyUserControlBase()
        {
            // Set binding to the Content property.
            var propertyPath = new PropertyPath("Content");
            var binding = new Binding { Path = propertyPath, Source = this };
            SetBinding(MyContentProperty, binding);
        }

        public object MyContent
        {
            get { return GetValue(MyContentProperty); }
            set { SetValue(MyContentProperty, value); }
        }

        private static void MyContentChangedCallback(
            DependencyObject dependencyObject,
            DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            Debugger.Break(); // Breaking here to show that binding to Content property has updated.
        }
    }
}

还有来自 MyUserControlBase MyUserControl (cs + xaml)。在构造函数中有默认的IntializeComponents()方法(注意:绑定是在基础构造函数中的此方法之前设置的)。在调用IntializeComponents()之前,在调用Content将内容设置为xaml中描述的内容之后,Content属性为null。但绑定不会更新目标属性。

MyUserControl.xaml.cs

namespace BindingBeforeInitComp
{
    using System.Diagnostics;

    using Windows.UI;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media;

    public sealed partial class MyUserControl : MyUserControlBase
    {
        public MyUserControl()
        {
            Debugger.Break(); // Here Content is null.

            InitializeComponent();

            Debugger.Break(); // Here Content is set, but as you can see there is no binding update.
        }

        private void ChangeContentClick(object sender, RoutedEventArgs e)
        {
            // Change content by a click. In this case the property changing should trigger update.
            Content = new Grid() { Background = new SolidColorBrush(Colors.Chartreuse) };
        }
    }
}

MyUserControl.xaml

<local:MyUserControlBase
    x:Class="BindingBeforeInitComp.MyUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:BindingBeforeInitComp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">

    <Grid Background="OrangeRed">
        <Button Click="ChangeContentClick" HorizontalAlignment="Center" Width="200" Height="150" Background="#FF00AE4F">Change content</Button>
    </Grid>
</local:MyUserControlBase>

完整来源:https://github.com/inTagger/Bugs/tree/master/BindingBeforeInitComp

UPDATE :我已经更新了GitHub上的源代码,添加了WPF(NET45)项目,以演示依赖属性和绑定应该如何工作的真实方式。是的,WPF没有这样的问题(行为/功能/错误)。

UPDATE2 :如果直接在构造函数中设置了内容依赖项属性 - 绑定有效,但是如果在InitializeComponents()内部设置了内容,则不行。

1 个答案:

答案 0 :(得分:0)

InitializeComponent方法的工作是加载您的Xaml,因此预计在运行之前您的所有UI元素都不可用。

考虑处理Loaded事件 - 您可以在基础构造函数中附加处理程序,并且在完全构造对象之后才会引发它。