【问题标题】:Style of a TextBox: Why is 'AcceptsReturn=true' not applied?文本框的样式:为什么不应用“AcceptsReturn=true”?
【发布时间】: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都包含在样式中。

TextWrappingVerticalScrollBarVisibility 都设置正确:

AcceptsReturn 不是:

任何想法,这里可能是什么问题?

【问题讨论】:

  • 出于好奇,为什么要在 OnApplyTemplate 而不是 EditableLabel 模板中分配样式?例如,&lt;TextBox x:Name="PART_TextBox" Style="{TemplateBinding TextBoxStyle}" ... /&gt;。此外,您的屏幕截图表明 AcceptsReturn 具有本地值。您的EditableLabel 类中有直接分配AcceptsReturn 属性的代码吗?如果是这样,您设置的本地值将优先于样式设置器。使用SetCurrentValue 避免更改值源。
  • 嗨,迈克,感谢您的回答!实际上,第一个问题是一个很好的问题,因为我不知道,实际上!我根据OnApplyTemplate 中的一些依赖属性处理控件的可见性,并且只是处理相同的样式。我已经按照您的建议对其进行了重构,并且:它有效!不过,我不明白为什么我的方法不起作用。我没有在本地任何地方设置AcceptsReturn。如果您将答案发布为答案,我将很高兴投票并解决问题:) 谢谢!!
  • 嗯,确实很奇怪。哦,很高兴我能帮上忙!我添加了一个答案。
  • 虽然您说其他设置器(AcceptsReturn 除外)工作,但请注意您以更可靠的方式检查它。我的意思是您在样式中所做的设置实际上可能与默认值相同,因此它可能会让您认为它适用于那些设置器。尝试添加一些更独特且易于识别的样式,例如添加Setter,将Background 设置为Red。我怀疑没有应用整个风格。确认是一个非常重要的步骤,以确保在某些方面有问题。
  • 我已经检查过了,样式正在被应用,其他设置器按预期改变了 TextBox 的行为......

标签: wpf xaml styles custom-controls


【解决方案1】:

您发布的屏幕截图表明AcceptsReturn 具有本地值,即通过显式调用属性设置器或SetValue 设置的值。 EditableLabel 中是否有任何代码明确设置了 AcceptsReturn 属性?如果是这样,您设置的本地值将优先于任何样式设置器。您可以通过使用SetCurrentValue 更改值同时保持值源不变来避免这种情况。

其次,与其在后面的代码中分配样式,在模板中简单地绑定样式通常更容易和更可靠,例如:

<TextBox x:Name="PART_TextBox" Style="{TemplateBinding TextBoxStyle}" ... />

你可以先试试这个,看看能不能得到更好的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多