WPF c#设置样式与参数

时间:2018-06-13 10:58:14

标签: c# wpf

我正在寻找一种方法来分配带参数的样式(大多数只是文本)并分配给指定的块

var replaceEnums = function (e) {

    //Purpose:
    //  Convert enumeration columns to use the string value.

    var hiddenCnt = 0;
    var groupCnt = 0;
    var dataCnt = false;

    //Loop through the columns and look for a values collection. 
    for (var iCol = 0; iCol < e.sender.columns.length; iCol++) {
        //if the column is hidden then do not do the replacement
        if (!e.sender.columns[iCol].hidden) {
            //If the values collection exists that means the column is an enumeration.
            if (e.sender.columns[iCol].values) {
                //Loop through each row
                for (var iRow = 1; iRow < e.workbook.sheets[0].rows.length; iRow++) {
                    if (e.workbook.sheets[0].rows[iRow].type == "data") {
                        var cell = e.workbook.sheets[0].rows[iRow].cells[iCol - hiddenCnt + groupCnt]
                        dataCnt = true;
                        //Loop through the enumeration and get the string value.  Stop once the correct
                        //value is found.
                        for (var iEnums = 0; iEnums < e.sender.columns[iCol].values.length; iEnums++) {
                            if (e.sender.columns[iCol].values[iEnums].value == cell.value) {
                                //Replace the enum value with the string value.
                                cell.value = e.sender.columns[iCol].values[iEnums].text
                                break
                            }
                        }
                    }
                    else {
                        //Track the number of group headers.  We need to track the 
                        //number of group headers because a group causes the columns
                        //to shift over by one for each grouping.
                        if (e.workbook.sheets[0].rows[iRow].type == "group-header") {
                            if (!dataCnt) {
                                groupCnt++;
                            }

                        }
                    }
                }
            }
        }
        else {
            //The column is hidden so add it to the count of hidden columns
            hiddenCnt++;
        }
    }
};

grid.bind("excelExport", replaceEnums);

有3个TextBlocks(field1,field2,field3),现在有任何方法可以将参数(参数是字符串类型)传递给此模板,并且此模板是通过循环生成的。怎么做?当然我可以在c#中创建所有内容但是认为创建字段(stackpanel)和分配参数会更容易

<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>

如果可以这样做,这将是完美的。除非有更好的。谢谢你的帮助。

1 个答案:

答案 0 :(得分:3)

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

DependencyProperty基本上是您自己的自定义属性的自定义类的声明,您希望在xaml条目期间公开它,并且也可以应用于您的样式模板。

一旦完成,您就可以定义自己的风格,充足的资源。将您的依赖项属性作为{TemplateBinding}包含在自定义属性中。

然后将新类的实例添加到表单中,并指定要使用的样式。我有一个示例显示在同一个类下使用两种样式。我首先开始使用全新的WPF应用程序。在MainWindow.xaml.cs中,我根据UserControl的类型定义了自己的类(然后可以保存任何其他控件,例如嵌套)。我添加了3个依赖项属性来反映您想要实现的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正在从

获取其值。
Text="{TemplateBinding MyText1}"  

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

一旦你掌握了基础知识,你可以像嵌入式堆栈面板那样美化你的模板

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

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

现在,所以你不必明确地为控件添加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个文本块并排显示你可以拥有一个类,并根据需要使它看起来不同。

每个问题/评论的修订。

如果要基于循环构建这些控件并动态添加它们,则只需在代码中分别设置属性。性能不应该很重要,因为已经声明了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 );
}

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