我有一个向用户表示自定义DataContext
的UserControl
。此控件还具有一个DependencyProperty
(带有PropertyChangedCallback
),该会影响向用户显示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>
我的调试输出显示以下内容:
将最终文本设置为值简单字符串 将最终文本设置为值简单字符串
我想知道是否可以在设置DataContext
之前设置DependencyProperty
Capitalize
?这样,FinalText
属性就不会设置两次。
为了使我的问题进一步复杂化,我的实际UserControl
需要支持渲染到Image
而不附加到Window
,这意味着Loaded
事件并不总是触发。
我可以添加一个正在使用的DependencyProperty
而不是DataContext
,但是仍然无法确保在填充所有其他DependencyProperties
后填充此新DependencyProperty
(示例中Capitalize
)
编辑:
正如评论中指出的,不建议使用DataContext
,我应该使用另一种Property
来设置需要渲染的内容。这很好而且很容易做到,但是仍然不能保证在解析所有其他Properties
后解析此新Property
。
我想这个问题可以重新表述为:如何检测用户控件是否已从 XAML 完全解析?
我想知道是否可以在设置
DataContext
之前设置依赖属性Capitalize
?
尝试更改顺序,即在设置DataContext
属性之前设置Capitalize
属性:
<local:MyControl Capitalize="True" DataContext="Simple string" />