在设置影响DataContext表示的属性之前设置WPF DataContext

时间:2018-02-23 11:09:23

标签: c# wpf dependency-properties

我有一个UserControl代表我对用户的自定义DataContext。此控件还有DependencyPropertyPropertyChangedCallback),会影响DataContext向用户显示的方式。

我的自定义UserControl XAML:

<UserControl x:Class="WpfApplication1.MyControl"
             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"
             x:Name="Me">
    <TextBox Text="{Binding FinalText,ElementName=Me}"/>
</UserControl>

我的自定义UserControl代码:

using System.Diagnostics;
using System.Windows;

namespace WpfApplication1
{
    public partial class MyControl
    {
        #region Static Fields and Constants
        public static readonly DependencyProperty CapitalizeProperty = DependencyProperty.Register(nameof(Capitalize), typeof(bool),
            typeof(MyControl), new PropertyMetadata(default(bool), CapitalizePropertyChanged));

        public static readonly DependencyProperty FinalTextProperty =
            DependencyProperty.Register(nameof(FinalText), typeof(string), typeof(MyControl), new PropertyMetadata(null));
        #endregion

        #region Properties and Indexers
        public bool Capitalize
        {
            get => (bool)GetValue(CapitalizeProperty);
            set => SetValue(CapitalizeProperty, value);
        }

        public string FinalText
        {
            get => (string)GetValue(FinalTextProperty);
            set
            {
                Debug.WriteLine($"Setting {nameof(FinalText)} to value {value}");
                SetValue(FinalTextProperty, value);
            }
        }
        #endregion

        #region Constructors
        public MyControl()
        {
            InitializeComponent();
            DataContextChanged += OnDataContextChanged;
        }
        #endregion

        #region Private members
        private static void CapitalizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is MyControl me)
                me.CreateFinalText(me.DataContext as string);
        }

        private void CreateFinalText(string text)
        {
            if (text != null)
            {
                FinalText = Capitalize ? text.ToUpperInvariant() : text.ToLowerInvariant();
            }
            else
            {
                FinalText = null;
            }
        }

        private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs args)
        {
            CreateFinalText(args.NewValue as string);
        }
        #endregion
    }
}

当我以下列方式使用UserControl时:

<Grid>
    <local:MyControl DataContext="Simple string" Capitalize="True"/>
</Grid>

我的调试输出显示以下内容:

  

将FinalText设置为值简单字符串
  将FinalText设置为值SIMPLE STRING

我想知道在DependencyProperty设置之前是否可以设置Capitalize DataContext?这样FinalText属性就不会设置两次。

为了使我的问题更加复杂,我的实际UserControl需要支持呈现Image而不附加到Window,这意味着Loaded事件没有总是触发。

我可以添加正在使用的DependencyProperty而不是DataContext,但是仍然无法确保在我所有其他{{1}之后填充此新DependencyProperty填充(示例中为DependencyProperties

修改
正如评论中指出的那样,不推荐使用Capitalize,而是应该使用另一个DataContext来设置需要呈现的内容。这很好,很容易做到,但是仍然无法保证在所有解析其他Property后解析这个新Property。 我想这个问题可以重新表述为:如何检测UserControl是否已经完全从XAML解析?

1 个答案:

答案 0 :(得分:0)

  

我想知道在Capitalize设置之前是否可以设置DependencyProperty DataContext

尝试更改顺序,即在设置Capitalize属性之前设置DataContext属性:

<local:MyControl Capitalize="True" DataContext="Simple string" />