[英]How to move items in a Grid
我有一個WPF Grid
,想根據用戶的輸入上下移動行。 到目前為止,這是我嘗試過的(用戶決定向上移動元素的示例):
RowDefinition currentRow = fieldsGrid.RowDefinitions[currentIndex];
fieldsGrid.RowDefinitions.Remove(currentRow);
fieldsGrid.RowDefinitions.Insert(currentIndex - 1, currentRow);
難道我做錯了什么? 由於使用此方法,UI保持不變。
這是一個使用ItemsControl進行所需操作的快速示例:
視圖模型
public class ListBoxViewModel
{
private static readonly List<string> sortList = new List<string>() { "Unsorted", "Sorted" };
public List<string> SortList { get { return sortList; } }
public ObservableCollection<ItemDetail> ItemDetails { get; set; }
#region Up Command
ICommand upCommand;
public ICommand UpCommand
{
get
{
if (upCommand == null)
{
upCommand = new RelayCommand(UpExecute);
}
return upCommand;
}
}
private void UpExecute(object param)
{
var id = param as ItemDetail;
if (id != null)
{
var curIndex = ItemDetails.IndexOf(id);
if (curIndex > 0)
ItemDetails.Move(curIndex, curIndex - 1);
}
}
#endregion Up Command
#region Down Command
ICommand downCommand;
public ICommand DownCommand
{
get
{
if (downCommand == null)
{
downCommand = new RelayCommand(DownExecute);
}
return downCommand;
}
}
private void DownExecute(object param)
{
var id = param as ItemDetail;
if (id != null)
{
var curIndex = ItemDetails.IndexOf(id);
if (curIndex < ItemDetails.Count-1)
ItemDetails.Move(curIndex, curIndex + 1);
}
}
#endregion Down Command
public ListBoxViewModel()
{
ItemDetails = new ObservableCollection<ItemDetail>()
{
new ItemDetail() { IsSelected = false, ItemName = "Customer Id", SortOrder = "Unsorted" },
new ItemDetail() { IsSelected = true, ItemName = "Customer Name", SortOrder = "Sorted" },
new ItemDetail() { IsSelected = false, ItemName = "Customer Age", SortOrder = "Unsorted" }
};
}
}
ItemDetail類(由我組成,使事情變得更容易)
public class ItemDetail
{
public bool IsSelected { get; set; }
public string ItemName { get; set; }
public string SortOrder { get; set; }
}
XAML
<UserControl.Resources>
<DataTemplate DataType="{x:Type vm:ItemDetail}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="CheckBoxGroup" />
<ColumnDefinition SharedSizeGroup="ItemNameGroup" />
<ColumnDefinition SharedSizeGroup="SortGroup" />
<ColumnDefinition Width="20" />
<ColumnDefinition SharedSizeGroup="UpArrowGroup" />
<ColumnDefinition SharedSizeGroup="DownArrowGroup" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" IsChecked="{Binding IsSelected}" VerticalAlignment="Center" />
<Label Grid.Column="1" Content="{Binding ItemName}" />
<ComboBox Grid.Column="2" ItemsSource="{Binding DataContext.SortList, RelativeSource={RelativeSource AncestorType={x:Type views:ListBoxExample}}}" SelectedItem="{Binding SortOrder}" />
<Button Grid.Column="4" Command="{Binding DataContext.UpCommand, RelativeSource={RelativeSource AncestorType={x:Type views:ListBoxExample}}}" CommandParameter="{Binding}">
<Image Source="..\images\up.png" Height="10" />
</Button>
<Button Grid.Column="5" Command="{Binding DataContext.DownCommand, RelativeSource={RelativeSource AncestorType={x:Type views:ListBoxExample}}}" CommandParameter="{Binding}">
<Image Source="..\images\down.png" Height="10" />
</Button>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid Grid.IsSharedSizeScope="True">
<ItemsControl ItemsSource="{Binding ItemDetails}" />
</Grid>
最后是結果:
然后在第一個項目上按下向下箭頭后:
希望這可以幫助。
這將是WPF方法來處理屏幕快照:
<Window x:Class="WpfApplication4.Window9"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window9" Height="300" Width="500">
<ItemsControl ItemsSource="{Binding Columns}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DataTemplate.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisConverter"/>
</DataTemplate.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="50"/>
<ColumnDefinition/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="25"/>
<ColumnDefinition Width="25"/>
</Grid.ColumnDefinitions>
<!-- This is your Key image, I used a rectangle instead, you can change it -->
<Rectangle Fill="Yellow" Visibility="{Binding IsPrimaryKey, Converter={StaticResource BoolToVisConverter}}" Margin="2"/>
<CheckBox IsChecked="{Binding IsSelected}" Grid.Column="1"/>
<TextBlock Text="{Binding Name}" Grid.Column="2"/>
<ComboBox ItemsSource="{Binding SortOrders}" SelectedItem="{Binding SortOrder}" Grid.Column="3" Margin="2"/>
<Button Content="Up" Grid.Column="4" Margin="2"
Command="{Binding DataContext.MoveUpCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=ItemsControl}}"
CommandParameter="{Binding}"/>
<Button Content="Down" Grid.Column="5" Margin="2"
Command="{Binding DataContext.MoveDownCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=ItemsControl}}"
CommandParameter="{Binding}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Window>
背后的代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using InduraClientCommon.MVVM;
using System.Collections.ObjectModel;
namespace WpfApplication4
{
public partial class Window9 : Window
{
public Window9()
{
InitializeComponent();
var vm = new ColumnListViewModel();
vm.Columns.Add(new ColumnViewModel() { IsPrimaryKey = true, Name = "Customer ID", SortOrder = SortOrder.Ascending });
vm.Columns.Add(new ColumnViewModel() {Name = "Customer Name", SortOrder = SortOrder.Descending});
vm.Columns.Add(new ColumnViewModel() {Name = "Customer Age", SortOrder = SortOrder.Unsorted});
DataContext = vm;
}
}
}
ViewModel:
public class ColumnListViewModel: ViewModelBase
{
private ObservableCollection<ColumnViewModel> _columns;
public ObservableCollection<ColumnViewModel> Columns
{
get { return _columns ?? (_columns = new ObservableCollection<ColumnViewModel>()); }
}
private DelegateCommand<ColumnViewModel> _moveUpCommand;
public DelegateCommand<ColumnViewModel> MoveUpCommand
{
get { return _moveUpCommand ?? (_moveUpCommand = new DelegateCommand<ColumnViewModel>(MoveUp, x => Columns.IndexOf(x) > 0)); }
}
private DelegateCommand<ColumnViewModel> _moveDownCommand;
public DelegateCommand<ColumnViewModel> MoveDownCommand
{
get { return _moveDownCommand ?? (_moveDownCommand = new DelegateCommand<ColumnViewModel>(MoveDown, x => Columns.IndexOf(x) < Columns.Count)); }
}
private void MoveUp(ColumnViewModel item)
{
var index = Columns.IndexOf(item);
Columns.Move(index, index - 1);
MoveUpCommand.RaiseCanExecuteChanged();
MoveDownCommand.RaiseCanExecuteChanged();
}
private void MoveDown(ColumnViewModel item)
{
var index = Columns.IndexOf(item);
Columns.Move(index, index + 1);
MoveUpCommand.RaiseCanExecuteChanged();
MoveDownCommand.RaiseCanExecuteChanged();
}
}
public class ColumnViewModel: ViewModelBase
{
private bool _isPrimaryKey;
public bool IsPrimaryKey
{
get { return _isPrimaryKey; }
set
{
_isPrimaryKey = value;
NotifyPropertyChange(() => IsPrimaryKey);
}
}
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
NotifyPropertyChange(() => IsSelected);
}
}
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
NotifyPropertyChange(() => Name);
}
}
private List<SortOrder> _sortOrders;
public List<SortOrder> SortOrders
{
get { return _sortOrders ?? (_sortOrders = Enum.GetValues(typeof(SortOrder)).OfType<SortOrder>().ToList()); }
}
private SortOrder _sortOrder;
public SortOrder SortOrder
{
get { return _sortOrder; }
set
{
_sortOrder = value;
NotifyPropertyChange(() => SortOrder);
}
}
}
public enum SortOrder {Unsorted, Ascending, Descending}
}
這是我屏幕上的樣子:
正如您在上面的示例中看到的那樣,我絕不會在代碼中操縱或創建UI元素,因為實際上這不是必需的。 每當您需要與屏幕上顯示的信息進行交互時,您都將與ViewModel
而不是View
交互。 這是UI與應用程序邏輯WPF之間明確的關注點分離,這是其他框架中完全沒有的。 在WPF中執行任何類型的N元素UI時,請考慮此方法為事實上的默認設置。
編輯:
與classic
方法相比,此方法的優點:
- 無需在代碼中操縱復雜的WPF類(IE UI元素)即可從屏幕顯示/獲取數據(只是簡單,簡單的屬性和INotifyPropertyChanged)
- 縮放效果更好(UI可以是任何東西,只要它尊重ViewModel屬性,您都可以將ComboBox更改為旋轉的3d粉紅色大象,每只腳的排序順序都可以。
- 無需在視覺樹上導航就可以找到上帝知道位置的元素。
- 沒有必要
foreach
任何東西。 只需一個簡單的Select
將您的數據(從您獲得的任何數據源)轉換為ViewModel
列表。
底線:如果您使用WPF方法,則WPF比當前存在的任何其他方法都簡單得多。
您正在更改RowDefinition的順序,這不是您想要的。 您想要將元素的分配更改為行,這由Grid.Row附加屬性確定
我將屬於每一行的所有控件放入一個容器(每行一個),然后使用Grid.SetRow更改容器。 了解如何從wpf中的后面代碼更改控件的網格行 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.