在ListView中拖动列时,列标签顺序不会更改

时间:2011-11-30 17:21:07

标签: wpf listview binding tabindex

是否可以将控件的TabIndex绑定到GridView中列的顺序?比如,我们将一个GridView的AllowColumnReorder设置为true,当我们将第二列拖到最后时,选项卡导航顺序将保持按列顺序排列:1 - > 3 - > 2,而不是1-> 2 - > 3通常。我想要做的是根据第二张图像上的实际列布局选项卡导航。 before moving column after moving column

我的kxaml代码:

   <Page
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <Grid>
      <ListView ItemsSource="2"
                Grid.Row="1">
                <ListView.View>
                    <GridView AllowsColumnReorder="True">
                        <GridViewColumn Header="One">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBox Width="100" Text="1"/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Two">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBox Width="100" Text="2"/>
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                        <GridViewColumn Header="Three">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBox Width="100" Text="3"/>                             
                               </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView>
                </ListView.View>
            </ListView>
      </Grid>
    </Page>

3 个答案:

答案 0 :(得分:2)

这是一个使用datagrid而不是

的示例
<DataGrid ItemsSource="2" Grid.Row="1">
  <DataGrid.CellStyle>
    <Style TargetType="{x:Type DataGridCell}">
      <Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
    </Style>
  </DataGrid.CellStyle>
  <DataGrid.Columns>
    <DataGridTemplateColumn Header="One">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <TextBox Width="100" Text="1" />
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    <DataGridTemplateColumn Header="Two">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <TextBox Width="100" Text="2" />
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    <DataGridTemplateColumn Header="Three">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <TextBox Width="100" Text="3" />
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>

修改

这是一个有效的listview解决方案,但我认为它不是最好的......

public class CustomGridViewColumn : GridViewColumn
{
  public static readonly DependencyProperty ColumnIndexProperty =
    DependencyProperty.Register("ColumnIndex", typeof(int), typeof(CustomGridViewColumn),
                                new FrameworkPropertyMetadata());

  public int ColumnIndex {
    get { return (int)GetValue(ColumnIndexProperty); }
    set { SetValue(ColumnIndexProperty, value); }
  }
}

public partial class Window1 : Window
{
  public Window1()
  {
    InitializeComponent();
    gridView.Columns.CollectionChanged+= new NotifyCollectionChangedEventHandler(gridView_Columns_CollectionChanged);
  }

  void gridView_Columns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
  {
    var index = 0;
    foreach(CustomGridViewColumn col in gridView.Columns){
      col.ColumnIndex=index++;
    }
  }
}

<ListView KeyboardNavigation.TabNavigation="Cycle">
  <ListView.View>
    <GridView x:Name="gridView" AllowsColumnReorder="True">
      <local:CustomGridViewColumn Header="One" x:Name="col1">
        <local:CustomGridViewColumn.CellTemplate>
          <DataTemplate>
            <TextBox Width="100" Text="1" TabIndex="{Binding Path=ColumnIndex, Mode=OneWay, ElementName=col1}"/>
          </DataTemplate>
        </local:CustomGridViewColumn.CellTemplate>
      </local:CustomGridViewColumn>
      <local:CustomGridViewColumn Header="Two" x:Name="col2">
        <local:CustomGridViewColumn.CellTemplate>
          <DataTemplate>
            <TextBox Width="100" Text="2" TabIndex="{Binding Path=ColumnIndex, Mode=OneWay, ElementName=col2}"/>
          </DataTemplate>
        </local:CustomGridViewColumn.CellTemplate>
      </local:CustomGridViewColumn>
      <local:CustomGridViewColumn Header="Three" x:Name="col3">
        <local:CustomGridViewColumn.CellTemplate>
          <DataTemplate>
            <TextBox Width="100" Text="3" TabIndex="{Binding Path=ColumnIndex, Mode=OneWay, ElementName=col3}"/>
          </DataTemplate>
        </local:CustomGridViewColumn.CellTemplate>
      </local:CustomGridViewColumn>
    </GridView>
  </ListView.View>

  <ListViewItem>1</ListViewItem>
  <ListViewItem>2</ListViewItem>
  <ListViewItem>3</ListViewItem>
</ListView>

希望这会有所帮助

答案 1 :(得分:1)

如果您改为使用DataGrid:列具有DisplayIndex属性,该属性保存当前索引,即使它们被重新排序也是如此。

答案 2 :(得分:1)

这是一个重要的开始。剩下要做的唯一事情就是遍历GridView的ListView的Items并在行(//! iterate ListView rows)中设置tab index foreach元素。一些逻辑可能搞砸了,因为代码匆忙..

XAML

<GridView 
    AllowsColumnReorder="True" 
    Controls:GridViewExtensions.DoTabIndexing="True">...

C#

/// <summary>Provides members helpful to <see cref="GridView"/>.</summary>
public static class GridViewExtensions
{
    #region DoTabIndexing

    [Category("Common")]
    [AttachedPropertyBrowsableForType(typeof(GridView))]
    public static bool GetDoTabIndexing(GridView gridView)
    {
        return (bool)gridView.GetValue(DoTabIndexingProperty);
    }
    public static void SetDoTabIndexing(GridView gridView, bool value)
    {
        gridView.SetValue(DoTabIndexingProperty, value);
    }

    public static readonly DependencyProperty DoTabIndexingProperty = 
        DependencyProperty.RegisterAttached(
            "DoTabIndexing",
            typeof(bool), // type
            typeof(GridViewExtensions), // container/holder/control
            new PropertyMetadata(default(bool), OnDoTabIndexingChanged)
            );

    private static void OnDoTabIndexingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var gridView = (GridView)d;
        if (gridView.AllowsColumnReorder == false) { return; }
        var newValue = (bool)e.NewValue;
        _indexWatch = new ColumnIndexWatch(gridView);
    }

    static ColumnIndexWatch _indexWatch;

    #endregion DoTabIndexing

    /// <summary>Watches for changes in a <see cref="GridView"/>'s columns.</summary>
    class ColumnIndexWatch
    {
        readonly GridView _gridView;
        public ColumnIndexWatch(GridView gridView)
        {
            _gridView = gridView;

            gridView.Columns.CollectionChanged += OnItemsPopulated;
        }

        void OnItemsPopulated(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action != NotifyCollectionChangedAction.Add)
            {
                _gridView.Columns.CollectionChanged -= OnItemsPopulated;
                _gridView.Columns.CollectionChanged += OnItemMoved;
                trax = new ColumnIndexCollection(_gridView.Columns);
                OnItemMoved(sender, e);
            }
        }

        ColumnIndexCollection trax;

        void OnItemMoved(object sender, NotifyCollectionChangedEventArgs e)
        {
            var movedColumn = e.NewItems[0] as GridViewColumn;
            if (movedColumn == null) { return; }

            trax.ApplyNewIndex(movedColumn, e.NewStartingIndex);
        }

        /// <summary>Represents a collection of <see cref="ColumnIndex"/></summary>
        class ColumnIndexCollection : Collection<ColumnIndex>
        {
            public ColumnIndexCollection(IEnumerable<GridViewColumn> columns)
                : base(Create(columns)) { }
            static IList<ColumnIndex> Create(IEnumerable<GridViewColumn> columns)
            {
                return columns.Select((t, i) => new ColumnIndex { GridViewColumn = t, Index = i }).ToList();
            }

            public void ApplyNewIndex(GridViewColumn column, int newIndex)
            {
                var movedByUser = Items.First(col => col.GridViewColumn == column);
                var placeTaken = Items.First(col => col.Index == newIndex);

                placeTaken.Index = movedByUser.Index;
                movedByUser.Index = newIndex;

                movedByUser.Update();
                placeTaken.Update();
                //! iterate ListView rows
            }
        }
        /// <summary>Represents a <see cref="System.Windows.Controls.GridViewColumn"/> and its index.</summary>
        class ColumnIndex
        {
            public GridViewColumn GridViewColumn { get; set; }
            public int Index { get; set; }
            public void Update()
            {
                KeyboardNavigation.SetTabIndex(GridViewColumn, Index);
            }
            public override string ToString()
            {
                return string.Format("{0} : {1}", Index, GridViewColumn);
            }
        }
    }
}