WPF:如何使XAML风格上可变的条件在自己的C#代码 [英] WPF: How to make styles in XAML conditional on a variable in your own C# code

查看:149
本文介绍了WPF:如何使XAML风格上可变的条件在自己的C#代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

WPF和XAML新手在这里....



我需要打一个WPF 触发 DataTrigger 在XAML代码到不是类的XAML控制的其他类一些C#代码。这是因为所有28000教程我读过只给出了触发一个简单的例子 DataTrigger 涉及<非常令人沮丧EM>属性已经存在的(例如鼠标悬停),他们没有给出如何与自己的C#代码比分扳成例子。



我有显示各种报表类型的屏幕。所有报表类型的XAML是相同的,不同之处在于诊断报告,我的要求是,在DataGrid细胞 TextBlock.TextAlignment =左,而配置所有其他报告(即默认值)应 TextBlock.TextAlignment =中心。 (还有一些其他方面的差异,为简单起见我只想说这是唯一的区别。)我真的不希望有复制整个XAML特殊情况的诊断报告,因为它的99%将是同其他报告。



要使用触发器,我想也许我需要我的同班同学自DependencyObject继承,所以我可以定义它的DependencyProperty的(作为一个WPF新手我意识到我可能会说一些很古怪的东西)。所以在我的C#代码,我有一类这样...

 命名空间为MyApplication 
{
公共枚举selectedReportType设置
{
EquipSummary,
EventSummary,
UserSummary,
DiagSummary
}

公共密封类ReportSettingsData:DependencyObject的
{
私有静态ReportSettingsData _instance; //单身

静态ReportSettingsData(){新ReportSettingsData(); }

私人ReportSettingsData()//私人,因为它是一个单身
{
如果(_instance == NULL)//唯一真正当通过静态构造函数
称为_instance =这一点; //这里,而不是设置静态构造函数,所以它是可立即
SelectedReport = SelectedReportType.EquipSummary; //设置初始/默认的报告类型
}

公共静态ReportSettingsData实例
{
{返回_instance; }
}

公共静态selectedReportType设置SelectedReport
{
{返回(selectedReportType设置)Instance.GetValue(SelectedReportProperty); }
集合{Instance.SetValue(SelectedReportProperty,值); }
}

公共静态只读的DependencyProperty SelectedReportProperty =
DependencyProperty.Register(SelectedReport的typeof(selectedReportType设置)的typeof(ReportSettingsData));
}
}



所以在我的XAML文件,我已经打了各种咒语触发 DataTrigger 并不能弄清楚如何使它发挥作用。在任何情况下,诊断报告有其他报告相同的默认特性



 <我:HeaderVisual X:CLASS = MyApplication.ReportsView
的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/presentation
的xmlns:X =htt​​p://schemas.microsoft.com/winfx / 2006 / XAML
的xmlns:我=CLR的命名空间:所有MyApplication>

< D​​ataGrid的名称=_ dgReport
columnWidth时=自动
CanUserAddRows =FALSE
VerticalScrollBarVisibility =自动
Horizo​​ntalScrollBarVisibility =自动
的ItemsSource ={结合}
IsReadOnly =真>
< D​​ataGrid.Resources>
<风格的TargetType =DataGridCell>
< setter属性=TextBlock.TextAlignmentVALUE =中心>< /二传手>
< Style.Triggers>
<! - 改写一些属性设置诊断报告... - > !
< -
< D​​ataTrigger绑定={结合我:ReportSettingsData.SelectedReport}VALUE =DiagSummary>
< D​​ataTrigger绑定={绑定路径=我:ReportSettingsData.SelectedReport}VALUE =DiagSummary>
- >
<触发属性=我:ReportSettingsData.SelectedReportVALUE =DiagSummary>
< setter属性=TextBlock.TextAlignmentVALUE =左>< /二传手>
< /触发>
< /Style.Triggers>
< /样式和GT;
< /DataGrid.Resources>
< / DataGrid的>

< /我:HeaderVisual>



我怎样才能让我的触发火当 ReportSettingsData.SelectedReport == SelectedReportType.DiagSummary


解决方案

如何使款式在XAML一个变量的条件在自己的C#代码




我建议你寻找到一个CellTemplate选择器( GridViewColumn .CellTemplateSelector属性(System.Windows.Controls的)),您可以在代码中做选择逻辑后面。



粗糙示例



简单地定义需要(4,但显示了两个)模板在资源

 < Window.Resources> 
<的DataTemplate X:键=EquipTemplate>

< TextBlock的保证金=2文本=装备前景=绿色/>

< / DataTemplate中>

<的DataTemplate X:键=EventTemplate>

< TextBlock的保证金=2文本=事件前景=红/>

< / DataTemplate中>

<的DataTemplate X:键=UserTemplate...

< /Window.Resources>



为网格单元的XAML模板的使用选择



 < D​​ataGridTemplateColumn标题=我的活动> 
< D​​ataGridTemplateColumn.CellTemplateSelector>
<局部:SelectedReportTypeTemplateSelector
EquipTemplate ={StaticResource的EquipTemplate}
EventTemplate ={StaticResource的EventTemplate}
的用户...
/>
< /DataGridTemplateColumn.CellTemplateSelector>
< / DataGridTemplateColumn>



代码隐藏



 公共类MeetingTemplateSelector:DataTemplateSelector 
{
公众的DataTemplate EquipTemplate {搞定;组; }

公众的DataTemplate EventTemplate {搞定;组; }

公众的DataTemplate UserTemplate {搞定;组; }

保护覆盖的DataTemplate SelectTemplateCore(对象项目,
DependencyObject的容器)
{
的DataTemplate结果;

开关(((ReportSettingsData)项).SelectedReport)
{
情况下EquipSummary:结果= EquipTemplate;打破;
情况下EventSummary:结果= EventTemplate;打破;
情况下UserSummary ..
}

返回结果;
}
}






更新



根据该品种的选择,使模板建议增长到超过30个模板的注释。另一种方式可能是在代替触发操作的操作属性来扩展目标类。例如说,我们需要显示为红色,它提供的实例,并绑定。

 公共部分MyClassInstance 
{
公共刷ColorMeAs
{
{返回this.IsValid? BrushGreen:BrushRed; }
}
...其他属性,例如:
}

然后绑定这样

 前景={结合ColorMeAs}



触发器



下面是从我的档案拉到数据触发的例子:

 <风格X:键=LabelStyle的TargetType ={X:类型标签}> 
< setter属性=VerticalAlignmentVALUE =顶部/>
< setter属性=宽度值=80/>
< setter属性=高度值=28/>
< Style.Triggers>
< D​​ataTrigger绑定={绑定路径= LoginInProcess}VALUE =真>
< setter属性=IsEnabledVALUE =FALSE/>
< / DataTrigger>
< D​​ataTrigger绑定={绑定路径= LoginInProcess}VALUE =FALSE>
< setter属性=IsEnabledVALUE =真/>
< / DataTrigger>
< /Style.Triggers>
< /样式和GT;


WPF and XAML newbie here....

I need to tie a WPF Trigger or DataTrigger in XAML code into some C# code in a class other than the class of the XAML control. This is very frustrating as all 28,000 tutorials I've read only give a trivial example for Trigger or DataTrigger that involves properties that already exist (e.g. MouseOver), none of them give examples of how to tie it in with your own C# code.

I have a screen for displaying various report types. The XAML for all of the report types is the same, except that for diagnostic reports, my requirements are that the DataGrid cells be configured with TextBlock.TextAlignment="Left", while all other reports (i.e. the default) should be TextBlock.TextAlignment="Center". (There are a few other differences; for brevity I'll just say that's the only difference.) I really don't want to have to duplicate the entire XAML to special-case the diagnostics report, since 99% of it would be the same as the other reports.

To use a Trigger, I thought perhaps I need my class to inherit from DependencyObject so I can define DependencyProperty's in it (being a WPF newbie I realize I may be saying some really outlandish things). So in my C# code, I have a class with this...

namespace MyApplication
{
   public enum SelectedReportType
   {
      EquipSummary,
      EventSummary,
      UserSummary,
      DiagSummary
   }

   public sealed class ReportSettingsData : DependencyObject
   {
      private static ReportSettingsData _instance; // singleton

      static ReportSettingsData() { new ReportSettingsData(); }

      private ReportSettingsData() // private because it's a singleton
      {
         if (_instance == null) // only true when called via the static constructor
            _instance = this; // set here instead of the static constructor so it's available immediately
         SelectedReport = SelectedReportType.EquipSummary; // set the initial/default report type
      }

      public static ReportSettingsData Instance
      {
         get { return _instance; }
      }

      public static SelectedReportType SelectedReport
      {
         get { return (SelectedReportType)Instance.GetValue(SelectedReportProperty); }
         set { Instance.SetValue(SelectedReportProperty, value); }
      }

      public static readonly DependencyProperty SelectedReportProperty =
         DependencyProperty.Register("SelectedReport", typeof(SelectedReportType), typeof(ReportSettingsData));
   }
}

So in my XAML file, I've played with various incantations of Trigger and DataTrigger and can't figure out how to make it work. In every case, the diagnostic report has the same default characteristics of the other reports.

<my:HeaderVisual x:Class="MyApplication.ReportsView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:my="clr-namespace:MyApplication">

   <DataGrid Name="_dgReport"
                ColumnWidth="Auto"
                CanUserAddRows="False"
                VerticalScrollBarVisibility="Auto"
                HorizontalScrollBarVisibility="Auto"
                ItemsSource="{Binding}"
                IsReadOnly="True">
      <DataGrid.Resources>
         <Style TargetType="DataGridCell">
            <Setter Property="TextBlock.TextAlignment" Value="Center"></Setter>
            <Style.Triggers>
               <!-- Override some property settings for Diagnostics reports... -->
               <!--
                  <DataTrigger Binding="{Binding my:ReportSettingsData.SelectedReport}"  Value="DiagSummary">
                  <DataTrigger Binding="{Binding Path=my:ReportSettingsData.SelectedReport}"  Value="DiagSummary">
               -->
               <Trigger Property="my:ReportSettingsData.SelectedReport"  Value="DiagSummary">
                  <Setter Property="TextBlock.TextAlignment" Value="Left"></Setter>
               </Trigger>
            </Style.Triggers>
         </Style>
      </DataGrid.Resources>
   </DataGrid>

</my:HeaderVisual>

How can I get my Trigger to fire when ReportSettingsData.SelectedReport == SelectedReportType.DiagSummary?

解决方案

How to make styles in XAML conditional on a variable in your own C# code

I recommend that you look into a CellTemplate Selector (GridViewColumn.CellTemplateSelector Property (System.Windows.Controls)) where you can do the selection logic in code behind.

Rough Example

Simply define the templates (4 but two shown) needed in the resource

<Window.Resources>
    <DataTemplate x:Key="EquipTemplate">

        <TextBlock Margin="2" Text="Equip" Foreground="Green"/>

    </DataTemplate>

    <DataTemplate x:Key="EventTemplate">

        <TextBlock Margin="2" Text="Event" Foreground="Red"/>

   </DataTemplate>

    <DataTemplate x:Key="UserTemplate" ...

</Window.Resources>

Xaml template usage selector for the grid cell

<DataGridTemplateColumn Header="My Event">
    <DataGridTemplateColumn.CellTemplateSelector>
        <local:SelectedReportTypeTemplateSelector
            EquipTemplate="{StaticResource EquipTemplate}"
            EventTemplate="{StaticResource EventTemplate}"
            User...
        />
    </DataGridTemplateColumn.CellTemplateSelector>
</DataGridTemplateColumn>

Code Behind

public class MeetingTemplateSelector : DataTemplateSelector
    {
        public DataTemplate EquipTemplate { get; set; }

        public DataTemplate EventTemplate { get; set; }

        public DataTemplate UserTemplate { get; set; }

        protected override DataTemplate SelectTemplateCore(object item, 
                  DependencyObject container)
        {
           DataTemplate result;

           switch( ((ReportSettingsData) item).SelectedReport)
           {
                case EquipSummary : result = EquipTemplate; break;
                case EventSummary : result = EventTemplate; break;
                case UserSummary ..
           }

          return result;
        }
    }


Update

As per the comment that the variety of choices makes the template suggestion grow to over 30 templates. One other way might be to extend the target class with operational properties in lieu of the triggered actions. For example say we need a red color shown, provide it on the instance and bind.

public Partial MyClassInstance
{
    public Brush ColorMeAs 
    {
         get { return this.IsValid ? BrushGreen  : BrushRed; }
    }
    ... other properties as such:
}

then bind as such

Foreground="{Binding ColorMeAs}"

Triggers

Here is an example of a data trigger pulled from my archive:

<Style x:Key="LabelStyle" TargetType="{x:Type Label}">
    <Setter Property="VerticalAlignment" Value="Top" />
    <Setter Property="Width" Value="80" />
    <Setter Property="Height" Value="28"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=LoginInProcess}" Value="True">
            <Setter Property="IsEnabled" Value="False" />
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=LoginInProcess}" Value="False">
            <Setter Property="IsEnabled" Value="True" />
        </DataTrigger>
    </Style.Triggers>
</Style>

这篇关于WPF:如何使XAML风格上可变的条件在自己的C#代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆