【问题标题】:ListBox ItemTemplate update using ToggleButton and attached Property使用 ToggleButton 和附加属性更新 ListBox ItemTemplate
【发布时间】:2020-11-20 10:55:22
【问题描述】:

我想在按下时用ToggleButton 实现ListBox,然后应该更新ListBox 的模板。一个模板将只有图标,一个将有图标和文本,如图所示。

我为此创建了一个附加属性并将其绑定到控件模板内的ToggleButton IsChecked 属性,但是此附加属性没有更新,我的模板也没有改变。 第一次加载应用程序时它正在工作。

<Style x:Key="NavigationListBoxStyle" TargetType="{x:Type ListBox}">
   <Setter Property="Background" Value="{StaticResource PrimaryDarkBrush}"/>
   <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
   <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
   <Setter Property="VerticalContentAlignment" Value="Center"/>
   <Setter Property="HorizontalContentAlignment" Value="Center"/>
   <Setter Property="SelectedIndex" Value="0"/>
   <Setter Property="Width" Value="Auto"/>

   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type ListBox}">
            <Border Background="{TemplateBinding Background}"
                                BorderThickness="0"
                                Padding="0"
                                SnapsToDevicePixels="true">
               <ScrollViewer Padding="{TemplateBinding Padding}"
                                          Focusable="false">
                  <StackPanel>
                     <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                     <ToggleButton IsChecked="{Binding local:IsOpenInfo.IsOpen,Mode=TwoWay}" Style="{DynamicResource ToggleButtonstyle}" Foreground="White">
                     </ToggleButton>
                  </StackPanel>
               </ScrollViewer>
            </Border>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
   <Setter Property="ItemTemplate" Value="{DynamicResource NavigationDataTemplate}"/>
   <Style.Triggers>
      <Trigger Property="local:IsOpenInfo.IsOpen" Value="True">
         <Setter Property="ItemTemplate" Value="{DynamicResource NavigationDataTemplate1}"/>
      </Trigger>
      <Trigger Property="local:IsOpenInfo.IsOpen" Value="False">
         <Setter Property="ItemTemplate" Value="{DynamicResource NavigationDataTemplate}"/>
      </Trigger>
   </Style.Triggers>
</Style>

<Style x:Key="ToggleButtonstyle" TargetType="{x:Type ToggleButton}">
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type ToggleButton}">
            <StackPanel Orientation="Horizontal">
               <iconPacks:PackIconMaterialDesign x:Name="MenuItemIcon" VerticalAlignment="Center" 
                                              HorizontalAlignment="Center" Margin="12" Kind="ArrowBack"/>
               <TextBlock Text="Collapse" VerticalAlignment="Center"  HorizontalAlignment="Center" />
            </StackPanel>
            <ControlTemplate.Triggers>
               <Trigger Property="IsChecked" Value="true">
                  <Setter TargetName="MenuItemIcon" Property="Kind" Value="ArrowForward"/>
                  <Setter TargetName="txtBlock" Property="Visibility" Value="Collapsed"/>
               </Trigger>
               <Trigger Property="IsChecked" Value="false">
                  <Setter TargetName="MenuItemIcon" Property="Kind" Value="ArrowBack"/>
                  <Setter TargetName="txtBlock" Property="Visibility" Value="Visible"/>
               </Trigger>
            </ControlTemplate.Triggers>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

<DataTemplate x:Key="NavigationDataTemplate">
   <iconPacks:PackIconMaterialDesign x:Name="MenuItemIcon" VerticalAlignment="Center" 
                                              HorizontalAlignment="Center" Margin="12"/>

   <DataTemplate.Triggers>
      <DataTrigger Binding="{Binding}" Value="Home">
         <Setter TargetName="MenuItemIcon" Property="Kind" Value="Home"/>
      </DataTrigger>
      <DataTrigger Binding="{Binding}" Value="Email">
         <Setter TargetName="MenuItemIcon" Property="Kind" Value="Email"/>
      </DataTrigger>
      <DataTrigger Binding="{Binding}" Value="Cloud">
         <Setter TargetName="MenuItemIcon" Property="Kind" Value="Cloud"/>
      </DataTrigger>
      <DataTrigger Binding="{Binding}" Value="Collapse">
         <Setter TargetName="MenuItemIcon" Property="Kind" Value="Mail"/>
      </DataTrigger>
   </DataTemplate.Triggers>
</DataTemplate>

<DataTemplate x:Key="NavigationDataTemplate1">
   <StackPanel Orientation="Horizontal">
      <iconPacks:PackIconMaterialDesign x:Name="MenuItemIcon" VerticalAlignment="Center" 
                                              HorizontalAlignment="Center" Margin="12"/>
      <TextBlock Text="{Binding}"  HorizontalAlignment="Center" VerticalAlignment="Center"/>
   </StackPanel>
   <DataTemplate.Triggers>
      <DataTrigger Binding="{Binding}" Value="Home">
         <Setter TargetName="MenuItemIcon" Property="Kind" Value="Home"/>
      </DataTrigger>
      <DataTrigger Binding="{Binding}" Value="Email">
         <Setter TargetName="MenuItemIcon" Property="Kind" Value="Email"/>
      </DataTrigger>
      <DataTrigger Binding="{Binding}" Value="Cloud">
         <Setter TargetName="MenuItemIcon" Property="Kind" Value="Cloud"/>
      </DataTrigger>
   </DataTemplate.Triggers>
</DataTemplate>

附加属性类如下:

public class IsOpenInfo
{
   public static bool GetIsOpen(DependencyObject obj)
   {
      return (bool)obj.GetValue(IsOpenProperty);
   }

   public static void SetIsOpen(DependencyObject obj, bool value)
   {
      obj.SetValue(IsOpenProperty, value);
   }

   // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
   public static readonly DependencyProperty IsOpenProperty =
      DependencyProperty.RegisterAttached("IsOpen", typeof(bool), typeof(IsOpenInfo), new PropertyMetadata(true));
}

我不知道为什么当IsChecked 属性更改并且样式触发器不起作用时附加属性没有更新?
有什么简单的方法可以实现吗?

有人指导我处理这个案子吗?

【问题讨论】:

    标签: c# wpf xaml data-binding


    【解决方案1】:

    您的样式是通过将TargetType 设置为ListBox 来定义的,触发器将解析您的自定义local:IsOpenInfo.IsOpen 属性的值,用于应用您的样式的ListBox 实例。

    但是,ToggleButton 是在 ListBoxControlTemplate 内定义的。它的IsChecked 绑定不会自动设置其模板父 控件上的附加属性的值。它将在ToggleButton 本身上设置。所以实际上,您是在ToggleButton 上设置值,但您在样式中的ListBox 上检查它,因此您正在对不同的值进行操作。

    您可以通过显式绑定到TemplatedParent 来使其工作,这是一个ListBox 实例。样式和切换按钮都将解析同一个 ListBox 实例的附加属性值。

    <ToggleButton IsChecked="{Binding (local:IsOpenInfo.IsOpen), RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                  Style="{DynamicResource ToggleButtonstyle}"
                  Foreground="White"/>
    

    【讨论】:

    • 嗨,是否可以让切换按钮也像 listitem 一样工作,因为只有当我按下图像时,如果我按下蓝色背景,它不会按预期切换
    • @NAGASREE ToggelButton 没有背景,因此在控制模板中将StackPanelBackground 设置为Transparent 应该可以工作:&lt;StackPanel Orientation="Horizontal" Background="Transparent"&gt;。如果您想要与列表框项相同的按钮效果,则必须相应地调整ToggleButton 的控件模板。
    猜你喜欢
    • 1970-01-01
    • 2014-08-16
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-28
    • 2010-10-03
    相关资源
    最近更新 更多