c# - WPF c# 设置样式带参数

标签 c# wpf

我正在寻找一种方法来为样式分配参数(其中大部分只是文本)并分配给指定的 block

<StackPanel Orientation="Horizontal">
    <StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock x:Name="field1" Text="Field1"/>
        </StackPanel>
    </StackPanel>
    <StackPanel>
        <Button BorderThickness="0">
            <Button.Content>
                <Border CornerRadius="18" BorderThickness="1" BorderBrush="#FFCFCFCF" >
                    <StackPanel Orientation="Horizontal">
                        <TextBlock  FontSize="10" Text="Default" Foreground="#FFCFCFCF" Margin="0" FontWeight="Black"/>
                    </StackPanel>
                </Border>
            </Button.Content>
        </Button>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <TextBlock x:Name="field2" Text="Field2"/>
        </StackPanel>
    </StackPanel>
    <StackPanel>
        <Button  BorderThickness="0">
            <Button.Content>
                <Border CornerRadius="18" BorderThickness="1" BorderBrush="#FFCFCFCF" >
                    <StackPanel Orientation="Horizontal">
                        <TextBlock FontSize="10" Text="RCC" Foreground="#FFCFCFCF" Margin="0" FontWeight="Black"/>
                    </StackPanel>
                </Border>
            </Button.Content>
        </Button>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <TextBlock x:Name="field3" Text="Field3"/>
        </StackPanel>
    </StackPanel>
    <Rectangle Width="1" Fill="Black" Height="42" VerticalAlignment="Center"/>
    <StackPanel Orientation="Horizontal">
        <Button  BorderThickness="0">
            <Button.Content>
                <Border CornerRadius="18" BorderThickness="1" BorderBrush="#FFCFCFCF" >
                    <StackPanel Orientation="Horizontal">
                        <TextBlock FontSize="10" Text="Custom" Foreground="#FFCFCFCF" FontWeight="Black"/>
                    </StackPanel>
                </Border>
            </Button.Content>
        </Button>
        <TextBox Width="90" Height="15"/>
        <Button  BorderThickness="0">
            <Button.Content>
                <Border CornerRadius="18" BorderThickness="1" BorderBrush="#FFCFCFCF" >
                    <StackPanel Orientation="Horizontal">
                        <TextBlock FontSize="10" Text="Apply" Foreground="#FFCFCFCF" FontWeight="Black"/>
                    </StackPanel>
                </Border>
            </Button.Content>
        </Button>
    </StackPanel>
</StackPanel>

有3个TextBlocks(field1,field2,field3),现在有没有办法给这个模板传递参数(参数是字符串类型),这个模板是通过循环生成的。以及如何去做?当然,我可以在 C# 中制作所有内容,但我认为创建字段(堆栈面板)并分配参数会容易得多

<stackpanel Style="{StaticResource mystyle}" param1="hello" param2="this" param3="world"/>

如果可以的话就完美了。除非有更好的。感谢您的帮助。

最佳答案

您可以通过额外使用 DependencyProperties 来声明自己的样式和控件模板。

DependencyProperty 基本上是对您自己的自定义属性的自定义类的声明,您希望在 xaml 输入期间公开这些属性,并且还可以应用于您的样式模板。

一旦完成,您就可以定义自己的风格,这方面有大量资源。将您的依赖项属性作为 {TemplateBinding} 包含到您的自定义属性中。

然后将新类的实例添加到表单中,并指定要使用的样式。我有一个示例显示在同一类下使用两种样式。我首先从一个全新的 WPF 应用程序开始。在 MainWindow.xaml.cs 中,我根据一种 UserControl 类型定义了自己的类(然后它可以容纳任何其他控件,例如您嵌套的控件)。我添加了 3 个依赖属性来反射(reflect)您想要实现的 3 个可能的文本值。

public class MyControl : UserControl
{
    public static readonly DependencyProperty MyText1Property =
        DependencyProperty.Register("MyText1", typeof(string),
        typeof(MyControl), new UIPropertyMetadata(""));

    public string MyText1
    {
        get { return (string)GetValue(MyText1Property); }
        set { SetValue(MyText1Property, value); }
    }


    public static readonly DependencyProperty MyText2Property =
        DependencyProperty.Register("MyText2", typeof(string),
        typeof(MyControl), new UIPropertyMetadata(""));

    public string MyText2
    {
        get { return (string)GetValue(MyText2Property); }
        set { SetValue(MyText2Property, value); }
    }


    public static readonly DependencyProperty MyText3Property =
        DependencyProperty.Register("MyText3", typeof(string),
        typeof(MyControl), new UIPropertyMetadata(""));

    public string MyText3
    {
        get { return (string)GetValue(MyText3Property); }
        set { SetValue(MyText3Property, value); }
    }
}

接下来,出于示例目的,我的应用程序名称为 StackOverflow,下面是整个 MainWindow.xaml。组件说明遵循代码。

<Window.Resources>
    <Style TargetType="{x:Type myApp:MyControl}" x:Key="MyControlStyle1">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type myApp:MyControl}" >
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{TemplateBinding MyText1}"/>
                        <TextBlock Text="{TemplateBinding MyText2}"/>
                        <TextBlock Text="{TemplateBinding MyText3}"/>
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>


    <Style TargetType="{x:Type myApp:MyControl}" x:Key="MyControlStyle">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type myApp:MyControl}" >
                    <StackPanel Orientation="Horizontal" Grid.Row="0">
                        <TextBlock Text="{TemplateBinding MyText1}"/>
                        <StackPanel>
                            <Button BorderThickness="0">
                                <Button.Content>
                                    <Border CornerRadius="18" BorderThickness="1" BorderBrush="#FFCFCFCF" >
                                        <StackPanel Orientation="Horizontal">
                                            <TextBlock  FontSize="10" Text="Default" Foreground="#FFCFCFCF" Margin="0" FontWeight="Black"/>
                                        </StackPanel>
                                    </Border>
                                </Button.Content>
                            </Button>
                            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                                <TextBlock Text="{TemplateBinding MyText2}"/>
                            </StackPanel>
                        </StackPanel>

                        <StackPanel>
                            <Button  BorderThickness="0">
                                <Button.Content>
                                    <Border CornerRadius="18" BorderThickness="1" BorderBrush="#FFCFCFCF" >
                                        <StackPanel Orientation="Horizontal">
                                            <TextBlock FontSize="10" Text="RCC" Foreground="#FFCFCFCF" Margin="0" FontWeight="Black"/>
                                        </StackPanel>
                                    </Border>
                                </Button.Content>
                            </Button>
                            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                                <TextBlock Text="{TemplateBinding MyText3}"/>
                            </StackPanel>
                        </StackPanel>
                        <Rectangle Width="1" Fill="Black" Height="42" VerticalAlignment="Center"/>
                        <StackPanel Orientation="Horizontal">
                            <Button  BorderThickness="0">
                                <Button.Content>
                                    <Border CornerRadius="18" BorderThickness="1" BorderBrush="#FFCFCFCF" >
                                        <StackPanel Orientation="Horizontal">
                                            <TextBlock FontSize="10" Text="Custom" Foreground="#FFCFCFCF" FontWeight="Black"/>
                                        </StackPanel>
                                    </Border>
                                </Button.Content>
                            </Button>
                            <TextBox Width="90" Height="15"/>
                            <Button  BorderThickness="0">
                                <Button.Content>
                                    <Border CornerRadius="18" BorderThickness="1" BorderBrush="#FFCFCFCF" >
                                        <StackPanel Orientation="Horizontal">
                                            <TextBlock FontSize="10" Text="Apply" Foreground="#FFCFCFCF" FontWeight="Black"/>
                                        </StackPanel>
                                    </Border>
                                </Button.Content>
                            </Button>
                        </StackPanel>
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>


    <!-- NOW, we can expand the custom properties-->
    <Style TargetType="{x:Type myApp:MyControl}" BasedOn="{StaticResource MyControlStyle}" />



</Window.Resources>


<Grid Height="150">
    <Grid.RowDefinitions>
        <RowDefinition Height="50" />
        <RowDefinition Height="50" />
        <RowDefinition Height="50" />
    </Grid.RowDefinitions>

    <myApp:MyControl MyText1="First String" MyText2="Second String" MyText3="Third String" 
        Style="{StaticResource MyControlStyle}"/>

    <myApp:MyControl MyText1="Another Line" MyText2="diff string" MyText3="all done" Grid.Row="1"/>

    <myApp:MyControl MyText1="Another Line" MyText2="diff string" MyText3="all done" Grid.Row="2"
        Style="{StaticResource MyControlStyle1}"/>

</Grid>

在主声明的顶部,我添加了

    xmlns:myApp="clr-namespace:StackOverflow"

这基本上表明,当在此 xaml 文件中时,我看到“myApp”的前缀,它类似于“使用 StackOverflow;”命令就像在代码中一样。所以现在我可以访问 xaml 的自定义类或该命名空间中的其他内容。

接下来我开始通过以下方式为自定义 MyControl 类声明我自己的“样式”

<Window.Resources>
    <Style TargetType="{x:Type myApp:MyControl}" x:Key="MyControlStyle1">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type myApp:MyControl}" >

...

如果您处理整个应用中使用的许多样式/模板,您可能想要创建一个单独的 ResourceDictionary。请注意“Syle”和自定义“ControlTemplate”是基于“myApp:MyControl”类结构的。现在,我可以在控件模板中使用“MyText1”、“MyText2”、“MyText3”元素。

x:Key="MyControlStyle1"就像通过给定名称创建一个变量,因此如果您需要明确说明要使用的样式,则可以使用它。第一种样式只是为了表明 3 个“MyText”属性可用并且文本从

Text="{TemplateBinding MyText1}"  

控件模板绑定(bind)到的类(因此是 TemplateBinding)。

一旦你掌握了基础知识,你就可以美化你的模板,就像你在较低的嵌套堆栈面板中所做的那样

<Style TargetType="{x:Type myApp:MyControl}" x:Key="MyControlStyle"> 

通过不同的 x:Key 名称声明。

现在,您不必显式地继续为您的控件添加 xaml 并说...顺便说一句,使用 MyControlStyle 的这种显式样式,我有以下内容

<Style TargetType="{x:Type myApp:MyControl}" BasedOn="{StaticResource MyControlStyle}" />

指示每当您看到“MyControl”的目标类型时,将样式默认为“MyControlStyle”,这样我就不必一直记住要这样做了。

终于实现了它的使用。代码的末尾有一个简单的 Grid 控件,其中包含 3 行。

<myApp:MyControl MyText1="First String" MyText2="Second String" MyText3="Third String" 
            Style="{StaticResource MyControlStyle}"/>

        <myApp:MyControl MyText1="Another Line" MyText2="diff string" MyText3="all done" Grid.Row="1"/>

        <myApp:MyControl MyText1="Another Line" MyText2="diff string" MyText3="all done" Grid.Row="2"
            Style="{StaticResource MyControlStyle1}"/>

请注意第一个实例,我可以显式声明要使用的样式。根据默认情况,第二个没有明确的样式,但第三个实例明确声明使用简化的“MyControlStyle1”,它只是并排显示的 3 个文本 block ,表明您可以拥有一个类并根据需要使其看起来不同。

根据问题/评论进行修订。

如果您基于循环构建这些控件并动态添加它们,您只需在代码中分别设置属性。性能不应该很重要,因为已经声明了 CLASS,您只是在列表中再添加一个。

foreach( var oneThing in YourListOfToBeAddedItems )
{
   var mc = new MyControl();
   mc.MyText1 = oneThing.TextFieldUsedForField1;
   mc.MyText2 = oneThing.FieldForSecondText;
   mc.MyText3 = oneThing.ThirdTextBasisForDisplay;
   // Now, add the "mc" to whatever your control is
   // can't confirm this line below as I dont know context
   // of your form and dynamic adding.
   YourWindowGridOrOtherControl.Controls.Add( mc );
}

此外,由于定义了默认样式,我不需要显式声明控件的“样式”。

关于c# - WPF c# 设置样式带参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50835495/

相关文章:

wpf - 如何使用WPF中的 slider 放大和缩小图像?

C#/WPF : Binding Combobox ItemSource in Datagrid to element outside of the DataContext

wpf - 如何提高 Canvas 渲染性能?

c# - 执行阅读器 : Connection property has not been initialized

c# - 反序列化期间的 JSON.Net Ignore Property

c# - 将用户映射到连接 ID 的最佳方法是什么

c# - 可编辑的 WPF GridView 行

c# - Metro Style 应用程序的颜色选择器?

c# - 在 CodeSnippetCompileUnit 中导入命名空间

c# - Mvc 从 "hidden"文件夹返回 403.14 而不是 404