【问题标题】:WinRT gridview Add tileWinRT gridview 添加磁贴
【发布时间】:2012-11-04 23:13:24
【问题描述】:

我有一个 GridView,它绑定到 List 的项目。我希望它有一个静态项目,以便用户可以单击它来添加更多项目。如果我点击其他项目,我会生成一个项目详细信息页面。

我怎样才能拥有与GridView 中的所有其他网格项目具有完全不同行为的静态图块?就像下图中的最后一个图块。

【问题讨论】:

  • 作为一个简单的技巧,您可以考虑在集合的末尾放置一个“虚拟”或“空”对象,以呈现不同的视图,并在单击时提供不同的交互。
  • 但是该对象如何在点击行为和视觉上具有不同的模板?
  • 好吧,这超出了我对WinRT 的知识范围,但如果它与其他XAML 实现类似,您应该可以控制绑定到集合中项目的视图,并且可以可能使用条件演示者或类型转换器来修改视图。至于单击行为,通常单击会转到视图模型或代码隐藏上的统一处理程序,该处理程序传递对绑定对象或元数据的引用,提供信息以获取绑定对象,然后您可以检查并采取相应的操作。

标签: c# windows gridview windows-runtime


【解决方案1】:

在我们的项目中,我们找到了一个干净的解决方案:您的 GridView ItemsSource 绑定到 ViewModel 的集合。最后一个可以是众所周知的 VM,例如 LoadMoreViewModel 实例。

它允许您创建一个 DataTemplateSelector 实现并将其设置为 GridView 的 ItemTemplateSelector 属性。

public class LoadMoreTemplateSelector: DataTemplateSelector
{
    public DataTemplate LoadMoreTemplate { get; set; }
    public DataTemplate DefaultTemplate { get; set; }


    protected override Windows.UI.Xaml.DataTemplate SelectTemplateCore(object item, Windows.UI.Xaml.DependencyObject container)
    {
        if (item is LoadMoreViewModel)
        {
            return LoadMoreTemplate;
        }
        else
        {
           return DefaultTemplate;
        }
    }
}

在您的 xaml 文件中创建此 TemplateSelector 的实例作为资源,并设置适当的模板:

<selectors:LoadMoreTemplateSelector x:Key="LoadMoreTemplateSelector" 
       DefaultTemplate="{StaticResource Template1}" 
       LoadMoreTemplate="{StaticResource LoadMoreTemplate}"/>

你的 gridView 可以使用这个模板选择器

<GridView ...
    ItemTemplateSelector="{StaticResource LoadMoreTemplateSelector}" />

LoadMoreTemplate 应该如下所示:

<DataTemplate x:Key="LoadMoreTemplate">
   <Button Command="{Binding LoadMore}" Content="+"/>
</DataTemplate>

唯一剩下的问题是您必须在 LoadMoreViewModel 中实现 ICommand 以将加载更多按钮绑定到模板中,或者创建一个 UserControl 以便能够对 Click 事件做出反应。

编辑: 这是一个简单的 ICommand 实现。单击按钮时,它将执行传递给构造函数的操作。

public class DelegateCommand : ICommand
{
    private readonly Predicate<object> _canExecute;
    private readonly Action<object> _execute;

    public event EventHandler CanExecuteChanged;

    public DelegateCommand(Action<object> execute) 
                   : this(execute, null)
    {
    }

    public DelegateCommand(Action<object> execute, 
                   Predicate<object> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public override bool CanExecute(object parameter)
    {
        if (_canExecute == null)
        {
            return true;
        }

        return _canExecute(parameter);
    }

    public override void Execute(object parameter)
    {
        _execute(parameter);
    }

    public void RaiseCanExecuteChanged()
    {
        if( CanExecuteChanged != null )
        {
            CanExecuteChanged(this, EventArgs.Empty);
        }
    }
}

当您实例化您的 LoadMoreViewModel 时,您可以提供当用户单击加载更多按钮时要执行的操作。

public class LoadMoreViewModel:BindableBase
{
   public ICommand LoadMore{get;private set;}
   public LoadMoreViewModel(Action<object> action)
   {
     LoadMore = new DelegateCommand(action);
   }
}

而在ViewModel页面中,当Loading more items in list时,移除当前列表末尾的LoadMoreViewModel,然后添加额外的item,最后再添加LoadMoreViewModel(如果需要的话):

public void LoadMoreItems()
{
  if(Items.Last() is LoadMoreViewModel)
  {
    Items.Remove(Items.Last());
  }
  //Insert here add new items logic.
  Items.Add(new LoadMoreViewModel(_=>LoadMoreItems());
}

【讨论】:

  • 哇,这看起来真不错。我会测试这个。你也有ICommand的例子吗?
  • @Eilistraee 这正是我所说的,+1 就是一个很好的例子。
【解决方案2】:

您可以简单地编辑 GridView 的控件模板:

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="GridView">
            <Border BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    Background="{TemplateBinding Background}">
                <ScrollViewer x:Name="ScrollViewer">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>

                        <!-- Your custom buttons -->
                        <StackPanel Orientation="Vertical"
                                    Grid.Column="0">

                        </StackPanel>

                        <ItemsPresenter Grid.Column="1"
                                        HeaderTemplate="{TemplateBinding HeaderTemplate}"
                                        Header="{TemplateBinding Header}"
                                        HeaderTransitions="{TemplateBinding HeaderTransitions}"
                                        Padding="{TemplateBinding Padding}" />
                    </Grid>
                </ScrollViewer>
            </Border>
        </ControlTemplate>
    </Setter.Value>
</Setter>

【讨论】:

  • 我没有测试过这个,但我认为它不会达到预期的效果。看起来它将按钮放在左栏中,但需要的是列表末尾的按钮。简单地交换列也不会这样做。挑战在于,当 GridView 的最后一列未充满项目时,您需要添加其他项目所在的按钮。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-24
  • 1970-01-01
相关资源
最近更新 更多