Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用自定义WPF控件时无法设置某些属性_C#_Wpf_Xaml_Custom Controls - Fatal编程技术网

C# 使用自定义WPF控件时无法设置某些属性

C# 使用自定义WPF控件时无法设置某些属性,c#,wpf,xaml,custom-controls,C#,Wpf,Xaml,Custom Controls,所以,我有一个名为WatermarkTextbox的自定义WPF控件,它扩展了TextBox。我唯一添加到代码中的是一个字符串依赖属性,用于保存水印文本。其余的魔法在Xaml中(如下) 在我的应用程序中使用时: <wpfControls:WatermarkTextbox Watermark="Text that disappears."/> 大多数情况下,这是有效的。我可以设置水印文本,当我开始输入一些文本时,它就会消失。当我更改字体大小时,它会同时更改水印和我输入的文本;

所以,我有一个名为WatermarkTextbox的自定义WPF控件,它扩展了TextBox。我唯一添加到代码中的是一个字符串依赖属性,用于保存水印文本。其余的魔法在Xaml中(如下)


在我的应用程序中使用时:

<wpfControls:WatermarkTextbox Watermark="Text that disappears."/>

大多数情况下,这是有效的。我可以设置水印文本,当我开始输入一些文本时,它就会消失。当我更改字体大小时,它会同时更改水印和我输入的文本;当我更改字体大小时,它只会更改输入的文本(这是我希望它执行的操作)。我可以更改文本框的大小。那都是肉汁

问题是当我开始尝试更改文本框的背景或边框属性时,就像这样

<wpfControls:WatermarkTextbox Watermark="Text that disappears." Background="Yellow"/>

什么也没发生。BorderBrush和BorderThickness的行为相同。现在,我知道了一些我不知道的重要概念。如果我将水印文本框的模板更改为以下内容,它将允许我在应用程序中设置所需的背景

<Style TargetType="wpfControls:WatermarkTextbox" >
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type wpfControls:WatermarkTextbox}">
                <Grid>
                    <TextBox x:Name="baseTextBox" 
                             Background="{TemplateBinding Background}"/>
                    <TextBlock Margin="5,0,0,0" x:Name="watermarkText" IsHitTestVisible="False" FontWeight="Light" FontStyle="Italic" Foreground="DarkGray"
                               Text="{Binding RelativeSource={RelativeSource AncestorType=wpfControls:WatermarkTextbox}, Path=Watermark}" Visibility="Hidden" Background="Transparent"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger SourceName="baseTextBox" Property="Text" Value="">
                        <Setter TargetName="watermarkText" Property="Visibility" Value="Visible"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我假设如果我对BorderBrush和BorderThickness做同样的操作,它们也会工作

所以,我的问题是,为什么?是什么使这些属性的行为不同于FontSize和FontWeight或高度和宽度?为什么我必须显式地将背景设置为{TemplateBinding Background},而不是FontSize?另外,我还需要为TemplateBinding设置哪些其他属性才能使其正常工作?

  • 它们是:;这是一个明显的特例。顺便说一句,这就是其中之一
  • 高度和宽度不是继承的,但是您已经有了默认情况下大小与其父级相同的XAML,并且您还没有做任何事情来禁用该行为
除此之外,您还需要显式执行
TemplateBinding
操作——或者,如果它们在运行时发生更改,则需要执行relativesource绑定:

{Binding PropertyName, RelativeSource={RelativeSource TemplatedParent}}

对此没有任何“首要原则”的解释;这些都只是随意的实现细节

某些属性是自动从其父属性继承的

这就是为什么不必设置字体大小

至于“还有什么”,这完全取决于您希望能够直接在用户控件上设置什么

虽然这不是防弹的,但我的一般经验法则是“如果它是属性窗口的
笔刷
选项卡中的属性,或者纯粹是为了视觉美学,它可能不会被继承”

从另一个角度来看,如果设置通常会产生奇怪的结果,那么它也可能不是继承的。示例:如果在
网格
上设置了
边距
属性,请想象每个子元素是否继承了相同的边距

因此,我通常会为所有非布局、视觉属性(背景、前景、边界笔刷等)添加模板绑定。或者我只是为我想直接设置到usercontrol的任何属性添加templatebindings。如果您从未打算(显式地或按样式)设置属性,则无需添加模板绑定

说得很好:“如果设置通常会产生奇怪的结果,那么它也可能不是继承的。例如:如果在网格上设置了Margin属性,想象一下如果每个子元素都继承了相同的Margin。”
{Binding PropertyName, RelativeSource={RelativeSource TemplatedParent}}