【发布时间】:2014-11-03 18:24:46
【问题描述】:
我在 WPF 中有一个自定义控件,它由一个切换按钮、一个 TextBlock 和一个 TextBox 组成。我基本上想做的是在选中切换按钮时显示 TextBox ,否则显示 TextBlock 。此外,我希望允许通过依赖属性定义控件上的样式属性,这些属性在运行时应用于 TextBlock 和 TextBox。默认模板如下所示:
<Style TargetType="{x:Type views:EditableLabel}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type views:EditableLabel}">
<Border Background="{TemplateBinding Background}">
<DockPanel Margin="0">
<telerik:RadToggleButton x:Name="PART_Toggle"
DockPanel.Dock="Right"
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsInEditMode, Mode=TwoWay}">
<Image Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ToggleImage}" Height="14" />
</telerik:RadToggleButton>
<TextBlock x:Name="PART_TextBlock"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text}" >
</TextBlock>
<TextBox x:Name="PART_TextBox"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
</TextBox>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
自定义控件有两个样式依赖属性,一个用于PART_TextBlock,一个用于PART_TextBox。样式在自定义控件的OnApplyTemplate 方法和两个依赖属性的属性更改回调中分配:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_textBlock = (TextBlock) GetTemplateChild("PART_TextBlock");
_textBox = (TextBox) GetTemplateChild("PART_TextBox");
_toggleButton = (RadToggleButton) GetTemplateChild("PART_Toggle");
ApplyStyles();
UpdateVisibilities();
}
private void ApplyStyles()
{
if (_textBlock != null) _textBlock.Style = TextBlockStyle;
if (_textBox != null) _textBox.Style = TextBoxStyle;
}
(这里没有显示回调,因为它们很简单,只是调用ApplyStyles()。
我使用这样的自定义控件:
<views:EditableLabel Text="{Binding SelectedToolbox.Description, Mode=TwoWay}"
CanEdit="{Binding SelectedToolbox.CanEdit}"
ToggleImage="../Resources/Images/edit-26.png">
<views:EditableLabel.TextBlockStyle>
<Style TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</views:EditableLabel.TextBlockStyle>
<views:EditableLabel.TextBoxStyle>
<Style TargetType="TextBox">
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="AcceptsReturn" Value="True" />
<Setter Property="VerticalScrollBarVisibility" Value="Visible" />
</Style>
</views:EditableLabel.TextBoxStyle>
</views:EditableLabel>
一切都按预期工作,除了 AcceptsReturn setter 没有应用,我觉得这很奇怪。我已经调试了ApplyStyles():样式分配正确并且两个setter都包含在样式中。
TextWrapping 和 VerticalScrollBarVisibility 都设置正确:
而AcceptsReturn 不是:
任何想法,这里可能是什么问题?
【问题讨论】:
-
出于好奇,为什么要在
OnApplyTemplate而不是EditableLabel模板中分配样式?例如,<TextBox x:Name="PART_TextBox" Style="{TemplateBinding TextBoxStyle}" ... />。此外,您的屏幕截图表明AcceptsReturn具有本地值。您的EditableLabel类中有直接分配AcceptsReturn属性的代码吗?如果是这样,您设置的本地值将优先于样式设置器。使用SetCurrentValue避免更改值源。 -
嗨,迈克,感谢您的回答!实际上,第一个问题是一个很好的问题,因为我不知道,实际上!我根据
OnApplyTemplate中的一些依赖属性处理控件的可见性,并且只是处理相同的样式。我已经按照您的建议对其进行了重构,并且:它有效!不过,我不明白为什么我的方法不起作用。我没有在本地任何地方设置AcceptsReturn。如果您将答案发布为答案,我将很高兴投票并解决问题:) 谢谢!! -
嗯,确实很奇怪。哦,很高兴我能帮上忙!我添加了一个答案。
-
虽然您说其他设置器(
AcceptsReturn除外)工作,但请注意您以更可靠的方式检查它。我的意思是您在样式中所做的设置实际上可能与默认值相同,因此它可能会让您认为它适用于那些设置器。尝试添加一些更独特且易于识别的样式,例如添加Setter,将Background设置为Red。我怀疑没有应用整个风格。确认是一个非常重要的步骤,以确保在某些方面有问题。 -
我已经检查过了,样式正在被应用,其他设置器按预期改变了 TextBox 的行为......
标签: wpf xaml styles custom-controls