0

例如,有一个派生自UserControl的类MyUserControlBase ,并且在其构造函数中有一组内容依赖属性的绑定

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 属性为空,在调用 Content 之后设置为 xaml 中描述的内容。但是绑定不会更新目标属性。

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

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

UPDATE2:如果直接在构造函数中设置 Content 依赖属性 - 绑定有效,但如果 Content 在 InitializeComponents() 中的某个位置设置则无效。

4

1 回答 1

0

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

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

于 2013-08-05T13:15:32.667 回答