【发布时间】:2019-04-09 23:06:07
【问题描述】:
以前我直接设置了 UserControl 的模板,而不是通过样式,并且一切正常:可以使用 this.Template.LoadContent() 或通过 this.Template.FindName("MyControlName 访问内容的根目录", this),两个调用都在 OnApplyTemplate 中完成,在 base.OnApplyTemplate() 调用之后。现在我需要一个样式,因为我使用两个 DataTrigger 来显示一个 Control 类型或另一个在 Binding 值的函数中。
通过使用下面的 XAML 进行调试,我看到在 base.OnApplyTemplate 调用 this.Template.LoadContent() 后返回一个 Border,其 Child 设置为空 ContentPresenter。我希望得到 wpf:TimeSpanPicker 元素。
我已阅读this 的答案,但由于上面介绍的调试结果,它对我没有帮助。与this answer 相同。
以前,我的 UserControl 直接在里面(在它的 XAML 文件中):
<UserControl.Template>
<ControlTemplate>
<wpf:TimeSpanPicker
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Name="MyTimeSpanPicker"
Margin="0,0,7,0"/>
</ControlTemplate>
</UserControl.Template>
现在我有了这个:
<UserControl.Style>
<Style TargetType="UserControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Mode=OneWay, Converter={StaticResource ClockToType}}"
Value="TimerData">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="UserControl">
<wpf:TimeSpanPicker
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Name="MyTimeSpanPicker"
Margin="0,0,7,0"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Mode=OneWay, Converter={StaticResource ClockToType}}"
Value="AlarmData">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="UserControl">
<Button>Not yet implemented</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Style>
代码隐藏包括:
internal wpf_timespanpicker.TimeSpanPicker GetMyTimeSpanPicker()
{
return (wpf_timespanpicker.TimeSpanPicker)Template.LoadContent();
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
GetMyTimeSpanPicker().TimeSpanValueChanged += MyTimeSpanPicker_TimeSpanValueChanged;
}
private void MyTimeSpanPicker_TimeSpanValueChanged(object sender, EventArgs e)
{
CurrentValue = GetMyTimeSpanPicker().TimeSpan;
}
ClockToType 值转换器只是将我的 Clock 类的实例之一转换为它们的类型名称。
更新
现在它部分工作,因为答案,但我需要在 UserControl 的 CurrentValue 依赖属性更改时设置 TimeSpanPicker 的 TimeSpan 依赖属性,并且当时间跨度选择器尚未更改时,可以更改 CurrentValue 依赖属性已加载。推迟此设置的最佳方法是什么?在设置之前调用 ApplyTemplate 似乎不起作用,因为我保留对 TimeSpanPicker 的引用的类变量为空:
private static void OnCurrentValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var o = d as ClockValueScreen;
o.ApplyTemplate();
o.MyTimeSpanPicker.TimeSpan = (TimeSpan)e.NewValue; // but here o.MyTimeSpanPicker is null
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate(); // execution reaches this point from the ApplyTemplate call above
}
private void MyTimeSpanPicker_Loaded(object sender, RoutedEventArgs e)
{
MyTimeSpanPicker = (wpf_timespanpicker.TimeSpanPicker)sender;
MyTimeSpanPicker.TimeSpanValueChanged += MyTimeSpanPicker_TimeSpanValueChanged;
}
【问题讨论】:
-
您可以尝试使用
TemplatePart属性将您的控件分成多个部分 -
TimeSpanValueChanged 不是路由事件吗?如果是,您可以使用样式和事件设置器或在控制级别处理它。
标签: c# wpf user-controls controltemplate