Порядок вкладок столбцов не меняется при перетаскивании столбцов в ListView - PullRequest
0 голосов
/ 30 ноября 2011

Можно ли привязать TabIndex элемента управления к порядку столбца в GridView? Скажем, у нас есть GridView с AllowsColumnReorder, установленным в 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 ]

2 голосов
/ 07 декабря 2011

вот пример с сеткой данных вместо

<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>

РЕДАКТИРОВАТЬ

вот решение со списком, которое работает, но я думаю, что это не самое лучшее ...

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 голос
/ 09 декабря 2011

Вот большое начало. Осталось только пройтись по элементам ListView в GridView и установить в строке элемент foreach index tab (//! iterate ListView rows). Некоторая логика может быть испорчена, поскольку код был поспешен ..

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);
            }
        }
    }
}
1 голос
/ 07 декабря 2011

Если вместо этого вы используете DataGrid: столбцы имеют свойство DisplayIndex , которое содержит текущий индекс, даже если они переупорядочены.

...