开发者

Problem with DataGrid Rows in WPF

I have a datagrid where I have two buttons on each row - one for moving a row up and one for moving a row down.

Each button has a command for allowing the user to move the selected row in either direction. The problem that I am facing is that it not working. I think the problem that I may have is that the other controls (combo boxes) on the rows are bound to data sources through the MVVM model where I am manipulating the rows on the code behind of the XAML thinking this would be the logical place in which to do it.

The code I have for one of the buttons is below:

private void MoveRowDown(object sender, ExecutedRoutedEventArgs e)
        {

            int currentRowIndex = dg1.ItemContainerGenerator.IndexFromContainer(dg1.ItemContainerGenerator.ContainerFromItem(dg1.SelectedItem));

            if (currentRowIndex >= 0)
            {
                this.GetRow(currentRowIndex + 1).IsSelected = true;
            }


        }
privat开发者_如何学运维e DataGridRow GetRow(int index)
        {
            DataGridRow row = (DataGridRow)dg1.ItemContainerGenerator.ContainerFromIndex(index);
            if (row == null)
            {
                dg1.UpdateLayout();
                dg1.ScrollIntoView(selectedAttributes.Items[index]);
                row = (DataGridRow)dg1.ItemContainerGenerator.ContainerFromIndex(index);
            }
            return row;
        }


You have to manipulate the CollectionView for the DataGrid. The CollectionView is responsible for how your data looks like basically. Here is a small example:

Let's assume you've bound your DataGrid to an ObservableCollection<T> named Items, and that T has a property called Index on which is sorted.
Initialize the ICollectionView in your ViewModel like this:

private ICollectionView cvs;

ctor(){
    /*your default init stuff*/
    /*....*/

    cvs = CollectionViewSource.GetDefaultView(items);
    view.SortDescriptions.Add(new SortDescription("Index",ListSortDirection.Ascending));
}

Now you can bind your button command to the Up command (also in your ViewModel):

private ICommand upCommand;
public ICommand Up
{
    get { return upCommand ?? (upCommand = new RelayCommand(p => MoveUp())); }
}

private void MoveUp()
{
    var current = (Item)view.CurrentItem;
    var i = current.Index;
    var prev = Items.Single(t => t.Index == (i - 1));
    current.Index = i - 1;
    prev.Index = i;
    view.Refresh(); //you need to refresh the CollectionView to show the changes.
}

WARNING: you have to add checks to see if there is a previous item etc. Alternatively you can specify a CanExecute delegate which checks the Index of the item and enables/disables the button.
(RelayCommand courtesy of Josh Smith/Karl Shifflett, can't find the correct link anymore)

Bind the command to you button like this (assuming your viewmodel is the DataContext of your window):

<DataGridTemplateColumn >
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <Button Content="Up" 
                  Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, 
                   Path=DataContext.Up}"/>
    </DataTemplate>
  </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>  

Hope this helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜