HeaderTemplate中的GridViewColumn命令

时间:2011-03-17 00:14:06

标签: wpf xaml gridviewcolumn

我有一个带GridViewColumn的GridView,标题使用带有textblox的模板来显示列名。 我想要一个附加到此列的命令,基本上当用户单击该列时,我的VM中的命令会被调用吗?

这是出于分类目的。

由于

2 个答案:

答案 0 :(得分:4)

可能为时已晚,无法帮助您,但对于寻找答案的其他人,您可以使用Attached Behaviours和GridViewColumnHeader.Click事件执行此操作(请参阅this MSDN article对标题项单击上的GridView进行排序)

我的代码如下; XAML:

<ListView Width="Auto" Height="Auto" Margin="12,12,12,12"
  ItemsSource="{Binding SearchResults}" 
  behav:GridViewColumnHeaderClick.Command="{Binding SortViewCommand}">

(其中'behav'是我附加行为的命名空间)。附加的行为类如下所示:

public class GridViewColumnHeaderClick
{
    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(GridViewColumnHeaderClick), new UIPropertyMetadata(null,
            GridViewColumnHeaderClick.CommandChanged));

    public static readonly DependencyProperty CommandBehaviourProperty =
        DependencyProperty.RegisterAttached("CommandBehaviour", typeof(GridViewColumnHeaderClickCommandBehaviour), typeof(GridViewColumnHeaderClick),
            new UIPropertyMetadata(null));

    public static ICommand GetCommand(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(CommandProperty);
    }

    public static void SetCommand(DependencyObject obj, ICommand value)
    {
        obj.SetValue(CommandProperty, value);
    }

    public static GridViewColumnHeaderClickCommandBehaviour GetCommandBehaviour(DependencyObject obj)
    {
        return (GridViewColumnHeaderClickCommandBehaviour)obj.GetValue(CommandBehaviourProperty);
    }

    public static void SetCommandBehaviour(DependencyObject obj, GridViewColumnHeaderClickCommandBehaviour value)
    {
        obj.SetValue(CommandBehaviourProperty, value);
    }

    private static void CommandChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        GridViewColumnHeaderClick.GetOrCreateBehaviour(sender).Command = e.NewValue as ICommand;
    }

    private static GridViewColumnHeaderClickCommandBehaviour GetOrCreateBehaviour(DependencyObject element)
    {
        GridViewColumnHeaderClickCommandBehaviour returnVal = GridViewColumnHeaderClick.GetCommandBehaviour(element);

        if (returnVal == null)
        {
            ListView typedElement = element as ListView;

            if (typedElement == null)
            {
                throw new InvalidOperationException("GridViewColumnHeaderClick.Command property can only be set on instances of ListView");
            }

            returnVal = new GridViewColumnHeaderClickCommandBehaviour(typedElement);

            GridViewColumnHeaderClick.SetCommandBehaviour(element, returnVal);
        }

        return returnVal;
    }
}

public class GridViewColumnHeaderClickCommandBehaviour
{
    public GridViewColumnHeaderClickCommandBehaviour(ListView element)
    {
        element.AddHandler(GridViewColumnHeader.ClickEvent, new RoutedEventHandler(this.ClickEventHandler));
    }

    public ICommand Command { get; set; }

    private void ClickEventHandler(object sender, RoutedEventArgs e)
    {
        ICommand localCommand = this.Command;
        object parameter = e.OriginalSource as GridViewColumnHeader;

        if ((localCommand != null) && localCommand.CanExecute(parameter))
        {
            localCommand.Execute(parameter);
        }
    }
}

然后您的命令可以基于MSDN文章中描述的事件处理程序:

    private void SortResults(string sortBy, ListSortDirection direction)
    {
        ICollectionView dataView = CollectionViewSource.GetDefaultView(this.SearchResults);    // where SearchResults is the data to which the ListView is bound
        dataView.SortDescriptions.Clear();

        SortDescription sortDescription = new SortDescription(sortBy, direction);
        dataView.SortDescriptions.Add(sortDescription);
        dataView.Refresh();
    }

    private void SortViewCommandHandler(object parameter)
    {
        GridViewColumnHeader typedParameter = parameter as GridViewColumnHeader;

        ListSortDirection direction;

        if (typedParameter != null)
        {
            if (typedParameter.Role != GridViewColumnHeaderRole.Padding)
            {
                if (typedParameter != this.previousSortHeader)
                {
                    direction = ListSortDirection.Ascending;
                }
                else
                {
                    if (this.previousSortDirection == ListSortDirection.Ascending)
                    {
                        direction = ListSortDirection.Descending;
                    }
                    else
                    {
                        direction = ListSortDirection.Ascending;
                    }
                }

                string headerLabel = typedParameter.Column.Header as string;

                this.SortResults(headerLabel, direction);

                if (direction == ListSortDirection.Ascending)
                {
                    typedParameter.Column.HeaderTemplate =
                      Resources["HeaderTemplateArrowUp"] as DataTemplate;
                }
                else
                {
                    typedParameter.Column.HeaderTemplate =
                      Resources["HeaderTemplateArrowDown"] as DataTemplate;
                }

                // Remove arrow from previously sorted header
                if ((this.previousSortHeader != null) && (this.previousSortHeader != typedParameter))
                {
                    this.previousSortHeader.Column.HeaderTemplate = null;
                }

                this.previousSortHeader = typedParameter;
                this.previousSortDirection = direction;
            }
        }
    }

我还没有想到一种MVVM-ish方式来设置标题模板(视图显然应该绑定到这里的某些东西),所以你自己就在那里!

请注意,我在附加行为的实现中稍微偏离了Josh Smith的文章 - 有一个单独的类使得多个有状态处理程序比使用静态事件处理程序方法更容易,所以这是我一般遵循的模式。 / p>

答案 1 :(得分:0)

您可以使用按钮替换标题模板中的文本块,然后将命令附加到该模板。如果需要,可以为按钮设置样式以删除边框。