切换开关内容未显示在 DataGrid 中

问题描述

我的切换开关使用自定义样式。应用了样式并且它工作正常并且显示“ON”或“OFF”。问题是当我将切换开关添加到 DataGrid 时。

DataGrid 项源绑定到模型,列 isActive 包含切换开关控件。如果 isActivetrue,切换将采用绿色,如果为 false,切换将采用红色,但不显示内容文本(“ON”、“OFF”)。

资源文件中切换开关的样式:

<Style x:Key="ActiveToggleSwitch" TargetType="{x:Type ToggleButton}">
    <Setter Property="IsChecked" Value="False"/>
    <Setter Property="HorizontalAlignment" Value="Left" />
    <Setter Property="VerticalAlignment" Value="Center" />
    <Setter Property="Template">

        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Grid x:Name="toggleSwitch">
                    <Border x:Name="Border" CornerRadius="10"
        Background="#C2283B"
        Width="90" Height="25">
                        <Border.Effect>
                            <DropShadowEffect ShadowDepth="0.6" Direction="0" Opacity="0.3" />
                        </Border.Effect>
                        <Ellipse x:Name="Ellipse" Fill="#FFFFFFFF" Stretch="Uniform"
             Margin="2 2 2 1"
             Stroke="Gray" StrokeThickness="0.2"
             HorizontalAlignment="Left" Width="22" >
                            <Ellipse.Effect>
                                <DropShadowEffect BlurRadius="10" ShadowDepth="1" Opacity="0.3" Direction="260" />
                            </Ellipse.Effect>
                        </Ellipse>
                    </Border>

                    <TextBlock x:Name="txtOff" Text="{Binding TextOFF}" Margin="0 0 40 0" VerticalAlignment="Center" FontWeight="DemiBold" HorizontalAlignment="Right" Foreground="White" FontSize="10" />
                    <TextBlock Opacity="0" x:Name="txtOn"  Text="{Binding TextON}" Margin="40 0 0 0" VerticalAlignment="Center" FontWeight="DemiBold"  Foreground="White" HorizontalAlignment="Left" FontSize="10" />
                </Grid>

                <ControlTemplate.Triggers>
                    <Trigger Property="ToggleButton.IsChecked" Value="True" >
                        <Trigger.EnterActions>

                            <BeginStoryboard>

                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetName="Border"
                                Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                To="#34A543"
                                Duration="0:0:0.1" />
                                    <ThicknessAnimation Storyboard.TargetName="Ellipse"
                                    Storyboard.TargetProperty="Margin"
                                    To="60 2 2 1"
                                    Duration="0:0:0.1" />
                                    <DoubleAnimation
                            Storyboard.TargetName="txtOff" 
                            Storyboard.TargetProperty="(TextBlock.Opacity)"
                            From="1.0" To="0.0" Duration="0:0:0:0.1"     />
                                    <DoubleAnimation
                            Storyboard.TargetName="txtOn" 
                            Storyboard.TargetProperty="(TextBlock.Opacity)"
                            From="0.0" To="1.0" Duration="0:0:0:0.1"  />
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                        <!--  some out fading  -->
                        <Trigger.ExitActions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetName="Border"
                                Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                To="#C2283B"
                                Duration="0:0:0.1" />
                                    <ThicknessAnimation Storyboard.TargetName="Ellipse"
                                    Storyboard.TargetProperty="Margin"
                                    To="2 2 2 1"
                                    Duration="0:0:0.1" />
                                    <DoubleAnimation
                            Storyboard.TargetName="txtOff" 
                            Storyboard.TargetProperty="(TextBlock.Opacity)"
                            From="0" To="1.0" Duration="0:0:0:0.1"       />
                                    <DoubleAnimation
                            Storyboard.TargetName="txtOn" 
                            Storyboard.TargetProperty="(TextBlock.Opacity)"
                            From="1.0" To="0.0" Duration="0:0:0:0.1" />
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.ExitActions>
                        <Setter Property="Foreground" Value="{DynamicResource IdealForegroundColorBrush}" />
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="False">
                    </Trigger>

                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Foreground" Value="{DynamicResource GrayBrush7}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="VerticalContentAlignment" Value="Center" />
</Style>

MainWindow.xaml:

<telerik:GridViewDataColumn x:Name="Activetoogle" IsReadOnly="True"  HeaderCellStyle="{StaticResource CustomGridViewHeaderCellStyle}" Header="{StaticResource ActivityTriggerSwitch}" DataMemberBinding="{Binding isActive}" Width="*">
    <telerik:GridViewDataColumn.CellTemplate>
        <DataTemplate>
            <StackPanel  Height ="Auto" >
                <ToggleButton  x:Name="isActive"  VerticalAlignment="Center" IsEnabled="False"  Style="{StaticResource ActiveToggleSwitch}"
                 HorizontalAlignment="Right" Width="auto" FlowDirection="RightToLeft" IsChecked="{Binding empisActive}" Content="{Binding ToogleContent}"  />
            </StackPanel>
        </DataTemplate>
    </telerik:GridViewDataColumn.CellTemplate>
</telerik:GridViewDataColumn>

MainWindow.xaml.cs

public MainWindow(){
    InitializeComponent();
    TextOFF = (string)Application.Current.Resources["NotActive"];
    TextON = (string)Application.Current.Resources["IsActive"];
}
// ...

我想在切换开关的列中显示文本,我该怎么做?

注意:如果未在数据模板内创建切换开关,则此方法有效。

切换按钮应包含文本(“ON”或“OFF”)。

DataGrid with toggle switches.

解决方法

TextOFFTextON 属性在您的 MainWindow 中定义,而不是在网格视图列中当前项的数据上下文中定义。由于您的绑定是硬连接到当前数据上下文,因此这不起作用,属性未在那里定义。

肮脏的解决方法

您可以像下面那样更改数据上下文,这是一种非常肮脏的解决方法我不建议这样做。它将数据上下文设置为 MainWindow,因此 ToggleButton 起作用并利用 StackPanel 数据上下文来绑定项目。

<ToggleButton  x:Name="isActive"
               VerticalAlignment="Center"
               IsEnabled="False"
               Style="{StaticResource ActiveToggleSwitch}"
               HorizontalAlignment="Right"
               Width="auto"
               FlowDirection="RightToLeft"
               DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type YourProject:MainWindow}}}"
               IsChecked="{Binding DataContext.empisActive,RelativeSource={RelativeSource AncestorType={x:Type StackPanel}}}"
               Content="{Binding DataContext.ToogleContent,RelativeSource={RelativeSource AncestorType={x:Type StackPanel}}}" />

具有依赖属性的解决方案

您不应直接在控件模板中对属性路径使用绑定。此绑定将始终依赖于确切的属性名称 TextOFFTextON 以及当前数据上下文,而是使用以下选项之一:

  • 创建从 ToggleButton 派生的自定义控件,并为 OnOff 文本添加依赖属性。
  • OnOff 文本创建自定义附加属性。

在这两种情况下,您都可以从外部绑定文本。我更喜欢第一个选项,因为您的开关按钮可能有其他属性,它可以公开适合其特殊行为或外观的属性。

public class SwitchButton : ToggleButton
{
   static SwitchButton()
   {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(SwitchButton),new FrameworkPropertyMetadata(typeof(SwitchButton)));
   }

   public static readonly DependencyProperty OffTextProperty = DependencyProperty.Register(
      nameof(OffText),typeof(string),typeof(SwitchButton));

   public static readonly DependencyProperty OnTextProperty = DependencyProperty.Register(
      nameof(OnText),typeof(SwitchButton));

   public string OffText
   {
      get => (string)GetValue(OffTextProperty);
      set => SetValue(OffTextProperty,value);
   }

   public string OnText
   {
      get => (string)GetValue(OnTextProperty);
      set => SetValue(OnTextProperty,value);
   }
}

现在,从模板中删除 x:Key 并将类型更改为 SwitchButton。如果没有键,样式将是隐式的并自动应用于范围内的所有 SwitchButton 控件。另请注意,绑定现在是绑定到 TemplateBinding 的依赖属性的 SwitchButton

<Style TargetType="{x:Type YourProject:SwitchButton}">
   <Setter Property="IsChecked"
           Value="False" />
   <Setter Property="HorizontalAlignment"
           Value="Left" />
   <Setter Property="VerticalAlignment"
           Value="Center" />
   <Setter Property="Template">

      <Setter.Value>
         <ControlTemplate TargetType="{x:Type YourProject:SwitchButton}">
            <Grid x:Name="toggleSwitch">
               <Border x:Name="Border"
                       CornerRadius="10"
                       Background="#C2283B"
                       Width="90"
                       Height="25">
                  <Border.Effect>
                     <DropShadowEffect ShadowDepth="0.6"
                                       Direction="0"
                                       Opacity="0.3" />
                  </Border.Effect>
                  <Ellipse x:Name="Ellipse"
                           Fill="#FFFFFFFF"
                           Stretch="Uniform"
                           Margin="2 2 2 1"
                           Stroke="Gray"
                           StrokeThickness="0.2"
                           HorizontalAlignment="Left"
                           Width="22">
                     <Ellipse.Effect>
                        <DropShadowEffect BlurRadius="10"
                                          ShadowDepth="1"
                                          Opacity="0.3"
                                          Direction="260" />
                     </Ellipse.Effect>
                  </Ellipse>
               </Border>

               <TextBlock x:Name="txtOff"
                          Text="{TemplateBinding OffText}"
                          Margin="0 0 40 0"
                          VerticalAlignment="Center"
                          FontWeight="DemiBold"
                          HorizontalAlignment="Right"
                          Foreground="White"
                          FontSize="10" />
               <TextBlock Opacity="0"
                          x:Name="txtOn"
                          Text="{TemplateBinding OnText}"
                          Margin="40 0 0 0"
                          VerticalAlignment="Center"
                          FontWeight="DemiBold"
                          Foreground="White"
                          HorizontalAlignment="Left"
                          FontSize="10" />
            </Grid>

            <ControlTemplate.Triggers>
               <Trigger Property="ToggleButton.IsChecked"
                        Value="True">
                  <Trigger.EnterActions>

                     <BeginStoryboard>

                        <Storyboard>
                           <ColorAnimation Storyboard.TargetName="Border"
                                           Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                           To="#34A543"
                                           Duration="0:0:0.1" />
                           <ThicknessAnimation Storyboard.TargetName="Ellipse"
                                               Storyboard.TargetProperty="Margin"
                                               To="60 2 2 1"
                                               Duration="0:0:0.1" />
                           <DoubleAnimation Storyboard.TargetName="txtOff"
                                            Storyboard.TargetProperty="(TextBlock.Opacity)"
                                            From="1.0"
                                            To="0.0"
                                            Duration="0:0:0:0.1" />
                           <DoubleAnimation Storyboard.TargetName="txtOn"
                                            Storyboard.TargetProperty="(TextBlock.Opacity)"
                                            From="0.0"
                                            To="1.0"
                                            Duration="0:0:0:0.1" />
                        </Storyboard>
                     </BeginStoryboard>
                  </Trigger.EnterActions>
                  <!--  some out fading  -->
                  <Trigger.ExitActions>
                     <BeginStoryboard>
                        <Storyboard>
                           <ColorAnimation Storyboard.TargetName="Border"
                                           Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                           To="#C2283B"
                                           Duration="0:0:0.1" />
                           <ThicknessAnimation Storyboard.TargetName="Ellipse"
                                               Storyboard.TargetProperty="Margin"
                                               To="2 2 2 1"
                                               Duration="0:0:0.1" />
                           <DoubleAnimation Storyboard.TargetName="txtOff"
                                            Storyboard.TargetProperty="(TextBlock.Opacity)"
                                            From="0"
                                            To="1.0"
                                            Duration="0:0:0:0.1" />
                           <DoubleAnimation Storyboard.TargetName="txtOn"
                                            Storyboard.TargetProperty="(TextBlock.Opacity)"
                                            From="1.0"
                                            To="0.0"
                                            Duration="0:0:0:0.1" />
                        </Storyboard>
                     </BeginStoryboard>
                  </Trigger.ExitActions>
                  <Setter Property="Foreground"
                          Value="{DynamicResource IdealForegroundColorBrush}" />
               </Trigger>
               <Trigger Property="IsMouseOver"
                        Value="False">
               </Trigger>

               <Trigger Property="IsEnabled"
                        Value="False">
                  <Setter Property="Foreground"
                          Value="{DynamicResource GrayBrush7}" />
               </Trigger>
            </ControlTemplate.Triggers>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
   <Setter Property="VerticalContentAlignment"
           Value="Center" />
</Style>

这允许您从外部绑定 OffOn 文本。在您的情况下,您需要使用 RelativeSource 绑定来访问 TextOFF 中的 TextONMainWindow 属性。

<YourProject:SwitchButton  x:Name="isActive"
                           VerticalAlignment="Center"
                           IsEnabled="False"
                           HorizontalAlignment="Right"
                           Width="auto"
                           FlowDirection="RightToLeft"
                           IsChecked="{Binding empisActive}"
                           Content="{Binding ToogleContent}"
                           OffText="{Binding TextOFF,RelativeSource={RelativeSource AncestorType={x:Type YourProject:MainWindow}}}"
                           OnText="{Binding TextON,RelativeSource={RelativeSource AncestorType={x:Type YourProject:MainWindow}}}"/>
,

您可以直接在 xaml 中使用字符串资源,在您的情况下使用 ViewModel 是不必要的步骤

xmlns:stringResources="clr-namespace:YourApp.Properties"

<TextBlock x:Name="txtOff" Text="{x:Static stringResources:Resources.NotActive}" Margin="0 0 40 0" VerticalAlignment="Center" FontWeight="DemiBold" HorizontalAlignment="Right" Foreground="White" FontSize="10" />

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...