【问题标题】:Why is my VisualStateTrigger not updating?为什么我的 VisualStateTrigger 没有更新?
【发布时间】:2016-07-18 04:57:43
【问题描述】:

我有以下情况: 我有一个包含两个列表视图的拆分视图。左边的项目选择触发右边的内容。如果窗口宽度小于 960 像素,我想根据 left-listview-selection 隐藏其中一个列表。

宽于 960 像素:

|1|2|

小于 960 像素且 selectedIndex == -1

|1|

小于 960 像素且 selectedIndex >= 0

|2|

我的方法是通过转换器来做到这一点:

class WindowStateConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        //Debugger.Break();
        if (Window.Current.Bounds.Width > 960) return 1;
        if ((int)value == -1) return -1;
        else return 0;
    }
    public object ConvertBack(object value, Type targetType, object parameter, string language)
    { throw new NotImplementedException(); }
}

在我的 xaml 中,我以这种方式使用 NuGet 上的 WindowsStateTriggers 库中的 CompareStateTrigger:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
      EntranceNavigationTransitionInfo.IsTargetElement="True">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="wideView">
                <VisualState.StateTriggers>
                    <triggers:CompareStateTrigger Value="{x:Bind SelectionList.SelectedIndex, Converter={StaticResource wsc}, Mode=OneWay}"
                                                  CompareTo="1" Comparison="Equal"/>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="ListColumn.Width" Value="360"/>
                    <Setter Target="DetailColumn.Width" Value="*"/>
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="narrowDetailView">
                <VisualState.StateTriggers>
                    <triggers:CompareStateTrigger Value="{x:Bind SelectionList.SelectedIndex, Converter={StaticResource wsc}, Mode=OneWay}"
                                                  CompareTo="0" Comparison="Equal"/>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="ListColumn.Width" Value="0"/>
                    <Setter Target="DetailColumn.Width" Value="*"/>
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="narrowListView">
                <VisualState.StateTriggers>
                    <triggers:CompareStateTrigger Value="{x:Bind SelectionList.SelectedIndex, Converter={StaticResource wsc}, Mode=OneWay}"
                                                  CompareTo="-1" Comparison="Equal"/>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="ListColumn.Width" Value="*"/>
                    <Setter Target="DetailColumn.Width" Value="0"/>
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="ListColumn" Width="0"/>
        <ColumnDefinition x:Name="DetailColumn" Width="*"/>
    </Grid.ColumnDefinitions>
    <ListView x:Name="SelectionList"
              Background="LightBlue"
              Grid.Column="0"/>
    <ListView x:Name="DetailsList"
              Background="LightGreen"
              Grid.Column="1"/>
</Grid>

在开始时,这工作正常,但是当我在运行时更改 Window-Size 时,没有任何反应。我什至在我的转换器中放置了 Debbuger.Break() 以检查它是否有作用,但它没有。你有什么解决办法吗?

编辑:

我按照 CompositeStateTrigger 的描述,我的 XAML 现在看起来像这样:

<Page
    x:Class="UWPTicketverwaltung.Views.OverviewPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWPTicketverwaltung.Views"
    xmlns:triggers="using:WindowsStateTriggers"
    xmlns:converters="using:UWPTicketverwaltung.Converters" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.Resources>
        <ResourceDictionary>
            <converters:WidthConverter x:Key="screenWidth"/>
        </ResourceDictionary>
    </Page.Resources>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
          EntranceNavigationTransitionInfo.IsTargetElement="True">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="wideAll">
                    <VisualState.StateTriggers>
                        <triggers:AdaptiveTrigger MinWindowHeight="960"/>
                        <!--<triggers:CompareStateTrigger Value="{x:Bind Converter={StaticResource screenWidth}, Mode=OneWay}"
                                                      CompareTo="959" Comparison="GreaterThan"/>-->
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="ListColumn.Width" Value="360"/>
                        <Setter Target="DetailColumn.Width" Value="*"/>
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="narrowOverview">
                    <VisualState.StateTriggers>
                        <triggers:CompositeStateTrigger Operator="And">
                            <triggers:CompareStateTrigger Value="{x:Bind SelectionList.SelectedIndex, Mode=OneWay}"
                                                          CompareTo="-1" Comparison="Equal"/>
                            <triggers:CompareStateTrigger Value="{x:Bind Converter={StaticResource screenWidth}, Mode=OneWay}"
                                                          CompareTo="960" Comparison="LessThan"/>
                        </triggers:CompositeStateTrigger>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="ListColumn.Width" Value="*"/>
                        <Setter Target="DetailColumn.Width" Value="0"/>
                    </VisualState.Setters>
                </VisualState>
                <VisualState x:Name="narrowDetails">
                    <VisualState.StateTriggers>
                        <triggers:CompositeStateTrigger Operator="And">
                            <triggers:CompareStateTrigger Value="{x:Bind SelectionList.SelectedIndex, Mode=OneWay}"
                                                          CompareTo="-1" Comparison="GreaterThan"/>
                            <triggers:CompareStateTrigger Value="{x:Bind Converter={StaticResource screenWidth}, Mode=OneWay}"
                                                          CompareTo="960" Comparison="LessThan"/>
                        </triggers:CompositeStateTrigger>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="ListColumn.Width" Value="0"/>
                        <Setter Target="DetailColumn.Width" Value="*"/>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="ListColumn" Width="360"/>
            <ColumnDefinition x:Name="DetailColumn" Width="*"/>
        </Grid.ColumnDefinitions>
        <ListView x:Name="SelectionList"
                  Background="LightBlue"
                  Grid.Column="0"/>
        <ListView x:Name="DetailsList"
                  Background="LightGreen"
                  Grid.Column="1"/>
    </Grid>
</Page>

我的 WidthConverter 看起来像这样:

public class WidthConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    { /*Debugger.Break();*/ return Window.Current.Bounds.Width; }
    public object ConvertBack(object value, Type targetType, object parameter, string language)
    { throw new NotImplementedException(); }
}

开始时一切看起来都很好,但是当我更改窗口大小时,触发器不会触发。知道我做错了什么吗?此外,我的转换器在启动时只触发一次。

编辑 2:

我按照说明将第二个 CompareStateTrigger 绑定到 Grid.Width。这是我的 XAML,它不再使用转换器:

<Grid x:Name="MainGrid" 
      Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
      EntranceNavigationTransitionInfo.IsTargetElement="True">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="wideAll">
                <VisualState.StateTriggers>
                    <triggers:CompareStateTrigger Value="{x:Bind MainGrid.Width, Mode=OneWay}"
                                                  CompareTo="959" Comparison="GreaterThan"/>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="ListColumn.Width" Value="420"/>
                    <Setter Target="DetailColumn.Width" Value="*"/>
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="narrowOverview">
                <VisualState.StateTriggers>
                    <triggers:CompositeStateTrigger Operator="And">
                        <triggers:CompareStateTrigger Value="{x:Bind SelectionList.SelectedIndex, Mode=OneWay}"
                                                      CompareTo="-1" Comparison="Equal"/>
                        <triggers:CompareStateTrigger Value="{x:Bind MainGrid.Width, Mode=OneWay}"
                                                      CompareTo="960" Comparison="LessThan"/>
                    </triggers:CompositeStateTrigger>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="ListColumn.Width" Value="*"/>
                    <Setter Target="DetailColumn.Width" Value="0"/>
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="narrowDetails">
                <VisualState.StateTriggers>
                    <triggers:CompositeStateTrigger Operator="And">
                        <triggers:CompareStateTrigger Value="{x:Bind SelectionList.SelectedIndex, Mode=OneWay}"
                                                      CompareTo="-1" Comparison="GreaterThan"/>
                        <triggers:CompareStateTrigger Value="{x:Bind MainGrid.Width, Mode=OneWay}"
                                                      CompareTo="960" Comparison="LessThan"/>
                    </triggers:CompositeStateTrigger>
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="ListColumn.Width" Value="0"/>
                    <Setter Target="DetailColumn.Width" Value="*"/>
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="ListColumn" Width="420"/>
        <ColumnDefinition x:Name="DetailColumn" Width="*"/>
    </Grid.ColumnDefinitions>
    <ListView x:Name="SelectionList"
              Background="LightBlue"
              Grid.Column="0">
        <!--<VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState>
                    <VisualState.StateTriggers>
                        <triggers:CompositeStateTrigger Operator="And">
                            <triggers:CompareStateTrigger/>
                        </triggers:CompositeStateTrigger>
                    </VisualState.StateTriggers>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>-->
    </ListView>
    <ListView x:Name="DetailsList"
              Background="LightGreen"
              Grid.Column="1"/>
</Grid>

现在的问题是,似乎根本没有使用 Width-Property,因为选择的唯一状态是“narrowOverview”(即使应用程序开始时宽度超过 960)。是不是绑定到 Grid.Width 的方式不对?

【问题讨论】:

  • 试试 AdaptiveTrigger。这是链接,例如stackoverflow.com/questions/36255941/…
  • 您似乎没有阅读我的完整问题,屏幕宽度不是唯一的标准。
  • 当你改变宽度时它不会调用转换器,因为宽度没有绑定到值属性。
  • 您可以做的是将宽度属性绑定到值而不是 SelectionList.SelectedIndex。您可以在 SelectionChanged 事件中更改所选索引时更改视觉状态。
  • 是的,但我想避免代码隐藏,尤其是在这种情况下。

标签: c# visual-studio xaml converter win-universal-app


【解决方案1】:

为此使用 CompositeStateTrigger。这是link

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" x:Name="MainGrid">

    <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState x:Name="wideAll">
                    <VisualState.StateTriggers>
                        <triggers:CompositeStateTrigger Operator="And">
                            <triggers:CompareStateTrigger  Value="{x:Bind SelectionList.SelectedIndex,Mode=OneWay}"
                                                      CompareTo="-1" Comparison="GreaterThan"/>
                            <triggers:CompareStateTrigger Value="{x:Bind  PageViewModel.ScreenWidth,Mode=OneWay}"
                                                  CompareTo="960" Comparison="GreaterThan"/>
                        </triggers:CompositeStateTrigger>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="ListColumn.Width" Value="420"/>
                        <Setter Target="DetailColumn.Width" Value="*"/>
                    </VisualState.Setters>
                </VisualState>
                <!--blue-->
                <VisualState x:Name="narrowOverview">
                    <VisualState.StateTriggers>
                        <triggers:CompositeStateTrigger Operator="And">
                            <triggers:CompareStateTrigger  Value="{x:Bind SelectionList.SelectedIndex,Mode=OneWay}"
                                                      CompareTo="-1" Comparison="Equal"/>
                           <triggers:CompareStateTrigger Value="{x:Bind  PageViewModel.ScreenWidth,Mode=OneWay}"
                                                      CompareTo="960" Comparison="LessThan"/>
                        </triggers:CompositeStateTrigger>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="ListColumn.Width" Value="*"/>
                        <Setter Target="DetailColumn.Width" Value="0"/>
                    </VisualState.Setters>
                </VisualState>
                <!--Green-->
                <VisualState x:Name="narrowDetails">
                    <VisualState.StateTriggers>
                        <triggers:CompositeStateTrigger Operator="And">
                            <triggers:CompareStateTrigger  Value="{x:Bind SelectionList.SelectedIndex,Mode=OneWay}"
                                                      CompareTo="-1" Comparison="GreaterThan"/>
                            <triggers:CompareStateTrigger Value="{x:Bind PageViewModel.ScreenWidth,Mode=OneWay}"
                                                      CompareTo="960" Comparison="LessThan"/>
                        </triggers:CompositeStateTrigger>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="ListColumn.Width" Value="0"/>
                        <Setter Target="DetailColumn.Width" Value="*"/>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="ListColumn" Width="420"/>
            <ColumnDefinition x:Name="DetailColumn" Width="*"/>
        </Grid.ColumnDefinitions>
        <ListView x:Name="SelectionList"
              Background="LightBlue"
              Grid.Column="0" >
        </ListView>
        <ListView x:Name="DetailsList"
              Background="LightGreen"
              Grid.Column="1" />
    </Grid>

Mainpage.xaml.cs

在此处定义 ViewModel 属性。在构造函数中将 Vm 分配给 DataContext

 public sealed partial class MainPage : Page, INotifyPropertyChanged
  {
    ViewModel viewModel;
    public ViewModel PageViewModel
      {
         get
         {
                return viewModel;

        }
        set
        {
        if(viewModel!=value)
          {
           viewModel= value;
             OnPropertyChanged("PageViewModel");
           }
        }
     }

    public event PropertyChangedEventHandler PropertyChanged;

      protected void OnPropertyChanged(string propertyName)
         {
            // the new Null-conditional Operators are thread-safe:
         this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));      

       }

public MainPage()
{
                               this.SizeChanged += MainPage_SizeChanged;
                                PageViewModel=(ViewModel) DataContext;
 }

            private void MainPage_SizeChanged(object sender, SizeChangedEventArgs e)
            {
             PageViewModel.ScreenWidth =(int)     Window.Current.Bounds.Width;
                                Debug.WriteLine(Vm.ScreenWidth);
            }

            }

Class1.cs

公共类 ViewModel:INotifyPropertyChanged {

        int screenWidth;
        public int ScreenWidth
        {
            get
            {
                return screenWidth;
            }
            set
            {
                if(value!=screenWidth)
                {
                    screenWidth = value;
                    OnPropertyChanged("ScreenWidth");
                }
            }

        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            // the new Null-conditional Operators are thread-safe:
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

【讨论】:

  • 我做到了,但问题似乎仍然存在。查看我的编辑
  • 使用 AdaptiveTrigger 有什么问题吗?您已使用 ComaprisionTrigger 作为窗口宽度
  • 是的,我使用它们是因为 AdaptiveTrigger 没有 MaxWindowWidth 属性。与比较我能够防止选择narrowDetails/narrowSelector-State,因为SelectedIndex的条件总是-1或大于-1
  • 更改宽度时是否调用屏幕宽度转换器?
  • 为网格命名并将其宽度属性绑定到您的第二个 CompareStateTrigger。我认为它是这样工作的
猜你喜欢
  • 1970-01-01
  • 2018-03-21
  • 2011-10-10
  • 2018-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-24
相关资源
最近更新 更多