【问题标题】:Change GridView Item DataTemplate based on seperate ViewModel Property in WinRT根据 WinRT 中单独的 ViewModel 属性更改 GridView 项 DataTemplate
【发布时间】:2013-12-18 05:07:51
【问题描述】:

我正在尝试做的是在 GridView 控件中显示一组项目,并根据单独按钮执行的命令更改这些项目的大小。

例如,在顶部有一排按钮分别显示“小”、“中”和“大”,并让 GridView 中的项目通过在相关状态下显示其项目来响应相关命令。

我有这样声明的gridview

<GridView ItemsSource="{Binding Squares}"

Square 是具有 Title 和 Fill 属性的 Square 对象的可观察集合。

起初,我通过在页面的资源部分中声明以下数据模板,沿着 DataTemplateSelector 路线走下去。

<DataTemplate x:Key="SquareSmallTemplate">
        <Grid Height="100" Width="100">
            <Rectangle Fill="{Binding Fill}"/>
            <TextBlock Text="{Binding Title}"/>
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="SquareMediumTemplate">
        <Grid Height="150" Width="150">
            <Rectangle Fill="{Binding Fill}"/>
            <TextBlock Text="{Binding Title}"/>
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="SquareLargeTemplate">
        <Grid Height="200" Width="200">
            <Rectangle Fill="{Binding Fill}"/>
            <TextBlock Text="{Binding Title}"/>
        </Grid>
    </DataTemplate>

这个想法是网格的高度和宽度属性对于相关模板是不同的。我在选择器中声明了以下数据模板

public DataTemplate SmallTemplate { get; set; }
public DataTemplate MediumTemplate { get; set; }
public DataTemplate LargeTemplate { get; set; }

并且在 SelecteTemplateCore 方法中我刚刚返回了相关模板

protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        string value = item as string;

        if (value != null)
        {
            if (value == "Small")
                return SmallTemplate;
            else if (value == "Medium")
                return MediumTemplate;
            else if (value == "Large")
                return LargeTemplate;
            return base.SelectTemplate(item, container);
        }
        else
        {
            return base.SelectTemplateCore(item, container);
        }            
    }

但是,使用此方法(以及根据 DataTemplateSelector 的设计)传入的对象是集合中的项目(Square)。

如果我希望每个项目具有不同的外观或其他东西,这很好,但我需要的是根据视图模型上的另一个属性更改的模板。

为此,我有以下内容

public string State {get; set;}

这设置为“小”、“中”或“大”,基于单独一行的三个按钮,这些按钮执行将这个属性设置为相关值的命令。

如何将 State 属性与更改为相关 DataTemplate 相关联?

我尝试的另一条路线是使用单个数据模板,该模板使用 VSM 为相关状态下的高度/宽度属性设置动画。但是,当状态发生变化时,我无法执行相关动画。

任何帮助都会很棒,谢谢

【问题讨论】:

    标签: c# gridview windows-runtime winrt-xaml datatemplate


    【解决方案1】:

    有几种方法可以做到这一点,我不确定哪种方法最好。在任何情况下,您都需要 1) 触发器和 2) 更新模板的操作。我倾向于使用PropertyChangedTriggerInvokeCommandAction

    <GridView x:Name="grid">
        <i:Interaction.Triggers>
            <ei:PropertyChangedTrigger Binding="{Binding State}">
                <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=UpdateTemplateCommand}" CommandParameter="{Binding State}" />
            </ei:PropertyChangedTrigger>
        </i:Interaction.Triggers>
    <GridView>
    

    (这里的“AncestorType”只是视图的根,所以请根据需要更改“UserControl”。)

    然后在视图中,您将有一个更新模板的ICommand

     UpdateTemplateCommand = new DelegateCommand(state => {
         switch ((string)state)
         {
             default:
             case "Small" : grid.ItemTemplate = "SquareSmallTemplate"; break;
             case "Medium" : grid.ItemTemplate = "SquareMediumTemplate"; break;
             case "Large" : grid.ItemTemplate = "SquareLargeTemplate"; break;
         }
     });
    

    IDK ... 写出来之后似乎有点复杂。也许您会发现最好将CurrentDataTemplate 属性添加到视图模型,并通过使用XamlReader 从字符串创建DataTemplates 来分配它。

    【讨论】:

    • 这是一个不错的方法,但在 WinRT 应用程序中不支持 AncestorType
    猜你喜欢
    • 1970-01-01
    • 2013-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多