英文:
WPF: Passing a data parameter into a style theme?
问题
我有一个样式,我在多个文本框中重复使用。在样式中,我定义了一个控件模板,而在控件模板内部,我有一些触发器。我想要能够从视图中将数据属性传递到其中一个触发器中。
以下是我当前在资源字典中定义的样式的简化版本:
<Style x:Key="TextBoxTheme" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding PARAMETER}" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="Red"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
有一个DataTrigger "(Binding PARAMETER}”,它将确定边框是否设置为红色。根据我在文本框中使用的位置,我想将其绑定到不同的变量。
我想能够从我的视图中将其作为参数传递。我想象中的实现方式如下(这只是我认为应该工作的一种方式的想法,但实际上不起作用):
<TextBox Style="{StaticResource TextBoxTheme, Parameter={Binding PARAMETER}}"/>
<TextBox Style="{StaticResource TextBoxTheme, Parameter={Binding DIFFERENT_PARAMETER}}"/>
由于我还无法弄清楚如何做到这一点,每次调用它时,我几乎都在重新编写相同的代码。
示例(在我的'Name'文本框中使用此样式):
<TextBox Text="{Binding Name}">
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource TextBoxTheme}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding DuplicateName}" Value="False">
<Setter Property="BorderBrush" TargetName="border" Value="Green"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
示例(当我希望在不同的绑定中使用相同样式时):
<TextBox Text="{Binding IpAddress}">
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource TextBoxTheme}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding DuplicateIP}" Value="False">
<Setter Property="BorderBrush" TargetName="border" Value="Green"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
有没有更好的方法来做到这一点?我找到了一篇文章,其中显示了如何将属性传递给样式(https://thomaslevesque.com/2011/10/01/wpf-creating-parameterized-styles-with-attached-properties/),但我没有看到如何将数据属性传递进去的示例。
英文:
I have a style that I re-use for multiple textboxes. Within the style, I define a control template - and within that control template, I have some triggers. I want to be able to pass a Data Property into one of those triggers from the View.
Here is a shortened version of my current style defined in a Resource Dictionary:
<Style x:Key="TextBoxTheme" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding PARAMETER}" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="Red"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
There is one DataTrigger "(Binding PARAMETER}" that will determine if the border is set to red or not. Depending on where I use this textbox, I want to bind that to a different variable.
I want to be able to pass that as a parameter from my View. I'm imagining something like this (just an idea of how I think it should work, but this doesn't work):
<TextBox Style="{StaticResource TextBoxTheme, Parameter={Binding PARAMETER}}"/>
<TextBox Style="{StaticResource TextBoxTheme, Parameter={Binding DIFFERENT_PARAMETER}}"/>
Since I can't figure out how to do that yet, I am almost rewriting the same code every time I call it.
Example (Using this style with my 'Name' textbox):
<TextBox Text="{Binding Name}">
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource TextBoxTheme}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding DuplicateName}" Value="False">
<Setter Property="BorderBrush" TargetName="border" Value="Green"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
Example (When I want to use this same style with a different binding):
<TextBox Text="{Binding IpAddress}">
<TextBox.Style>
<Style TargetType="TextBox" BasedOn="{StaticResource TextBoxTheme}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding DuplicateIP}" Value="False">
<Setter Property="BorderBrush" TargetName="border" Value="Green"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
Is there a better way of doing this? I found an article that shows you how to pass a property into a style (https://thomaslevesque.com/2011/10/01/wpf-creating-parameterized-styles-with-attached-properties/) but I don't see it working with passing a data property.
答案1
得分: 1
一般来说,对于重用现有样式,Style.Triggers 要优于 ControlTemplate.Triggers,因为 Style.Triggers 可以在派生的样式中定义。
一个简单的基础样式可能如下:
<Style x:Key="TextBoxTheme" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="BorderThickness" Value="2"/>
</Style>
然后,您可以定义两个不同 Style.Triggers 的派生样式。
<Style x:Key="TextBoxTheme1" TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxTheme}">
<Style.Triggers>
<DataTrigger Binding="{Binding PARAMETER}" Value="True">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="TextBoxTheme2" TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxTheme}">
<Style.Triggers>
<DataTrigger Binding="{Binding DuplicateName}" Value="False">
<Setter Property="BorderBrush" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
或者,如果您想为每个 TextBox 指定 Style.Triggers,可以更容易地在每个 TextBox 内定义一个样式。
<TextBox Text="example">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxTheme}">
<Style.Triggers>
<DataTrigger Binding="{Binding DuplicateIP}" Value="False">
<Setter Property="BorderBrush" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
英文:
In general, for reusing an existing Style, Style.Triggers are better than ControlTemplate.Triggers because Style.Triggers can be defined at an derived Style.
A simple base Style would be like:
<Style x:Key="TextBoxTheme" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="BorderThickness" Value="2"/>
</Style>
Then you can define two derived Styles of different Style.Triggers.
<Style x:Key="TextBoxTheme1" TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxTheme}">
<Style.Triggers>
<DataTrigger Binding="{Binding PARAMETER}" Value="True">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="TextBoxTheme2" TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxTheme}">
<Style.Triggers>
<DataTrigger Binding="{Binding DuplicateName}" Value="False">
<Setter Property="BorderBrush" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
Or if you want to specify Style.Triggers for each TextBox, it would be easier to define a Style inside each TextBox.
<TextBox Text="example">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxTheme}">
<Style.Triggers>
<DataTrigger Binding="{Binding DuplicateIP}" Value="False">
<Setter Property="BorderBrush" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
答案2
得分: 0
如果您特别希望这个与某个样式一起使用,那么您可以使用附加的依赖属性。
您可以将其绑定到控件中的任何喜欢的内容。
<TextBox Style="{StaticResource TextBoxTheme}"
local:Attached.AbstractedProperty="{Binding .....}"/>
然后在您的样式中引用已知属性
<DataTrigger Binding="{Binding Path=(local:Attached.AbstractedProperty), RelativeSource={RelativeSource Self}}" Value="False">
<Setter Property="BorderBrush" Value="Green"/>
英文:
If you particularly want this to work with the one style then you could use an attached dependency property.
You can bind that to whatever you like in the control.
<TextBox Style="{StaticResource TextBoxTheme}"
local:Attached.AbstractedProperty="{Binding .....}"/>
You then reference that known property in your style
<DataTrigger Binding="{Binding Path=(local:Attached.AbstractedProperty), RelativeSource={RelativeSource Self}}" Value="False">
<Setter Property="BorderBrush" Value="Green"/>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论