我知道这很长,但请耐心等待。
我创建了一个Windows应用程序商店程序,与使用MVVM轻量级框架的MVVM光样本中的Laurent Bugnion的“MyFriends”程序非常相似。
在他的程序中,他使用gridview的SelectedItem属性来跟踪哪个项目是所选项目。
问题是,我让用户能够在GridView上选择多个项目,然后使用App Bar上的按钮对其进行操作。因为这个SelectedItem不起作用。
有没有人知道如何使用多选GridView进行此操作?我已经根据WPF上的一些文章尝试了GridViewItem的IsSelected属性,但这似乎不起作用。 SelectedTimesheets getter在调用时总是返回空。以下是我到目前为止的情况:
MainPage.xaml(绑定到带有子TimesheetViewModel可观察集合的MainViewModel):
<GridView
x:Name="itemGridView"
IsItemClickEnabled="True"
ItemsSource="{Binding Timesheets}"
ItemTemplate="{StaticResource TimesheetTemplate}"
Margin="10"
Grid.Column="0"
SelectionMode="Multiple"
helpers:ItemClickCommand.Command="{Binding NavigateTimesheetCommand}" RenderTransformOrigin="0.738,0.55" >
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</GridView.ItemContainerStyle>
</GridView>
MainViewModel(从完整代码中删除):
public class MainViewModel : ViewModelBase
{
private readonly IDataService _dataService;
private readonly INavigationService _navigationService;
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel(IDataService dataService, INavigationService navigationService)
{
_dataService = dataService;
_navigationService = navigationService;
Timesheets = new ObservableCollection<TimesheetViewModel>();
ExecuteRefreshCommand();
}
public ObservableCollection<TimesheetViewModel> Timesheets
{
get;
private set;
}
public IEnumerable<TimesheetViewModel> SelectedTimesheets
{
get { return Timesheets.Where(o => o.IsSelected); }
}
private async void ExecuteRefreshCommand()
{
var timesheets = await _dataService.GetTimesheets("domain\\user");
if (timesheets != null)
{
Timesheets.Clear();
foreach (var timesheet in timesheets)
{
Timesheets.Add(new TimesheetViewModel(timesheet));
}
}
}
}
TimesheetViewModel:
public class TimesheetViewModel: ViewModelBase
{
public bool IsSelected { get; set; }
public Timesheet Model
{
get;
private set;
}
public TimesheetViewModel(Timesheet model)
{
Model = model;
}
}
如果我手动设置IsSelected属性,则SelectedTimesheets lambda可以工作,因此问题出在XAML与IsSelected属性绑定的某处。
任何帮助都将不胜感激。
答案 0 :(得分:6)
当然,我知道你的意思。太糟糕了,这不是自动化,但事实并非如此。该解决方案涉及一个继承自GridView
的简单自定义GridView
。没有什么太疯狂的,也就是说,如果你让它沉入其中。这是代码,我只是测试了它:
这是你的XAML:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions >
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<local:MyGridView ItemsSource="{Binding Items}" SelectionMode="Multiple"
BindableSelectedItems="{Binding Selected}" />
<local:MyGridView Grid.Column="1" ItemsSource="{Binding Selected}" />
</Grid>
这是您的视图模型(超简化):
public class ViewModel
{
ObservableCollection<string> m_Items
= new ObservableCollection<string>(Enumerable.Range(1, 100).Select(x => x.ToString()));
public ObservableCollection<string> Items { get { return m_Items; } }
ObservableCollection<object> m_Selected = new ObservableCollection<object>();
public ObservableCollection<object> Selected { get { return m_Selected; } }
}
这是你的自定义gridview:
public class MyGridView : GridView
{
public ObservableCollection<object> BindableSelectedItems
{
get { return GetValue(BindableSelectedItemsProperty) as ObservableCollection<object>; }
set { SetValue(BindableSelectedItemsProperty, value as ObservableCollection<object>); }
}
public static readonly DependencyProperty BindableSelectedItemsProperty =
DependencyProperty.Register("BindableSelectedItems",
typeof(ObservableCollection<object>), typeof(MyGridView),
new PropertyMetadata(null, (s, e) =>
{
(s as MyGridView).SelectionChanged -= (s as MyGridView).MyGridView_SelectionChanged;
(s as MyGridView).SelectionChanged += (s as MyGridView).MyGridView_SelectionChanged;
}));
void MyGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (BindableSelectedItems == null)
return;
foreach (var item in BindableSelectedItems.Where(x => !this.SelectedItems.Contains(x)).ToArray())
BindableSelectedItems.Remove(item);
foreach (var item in this.SelectedItems.Where(x => !BindableSelectedItems.Contains(x)))
BindableSelectedItems.Add(item);
}
}
只有一个新属性BindableSelectedItems
。
祝你好运!
答案 1 :(得分:1)
首先,我更改了XAML以接受新的辅助方法 SelectionChangedCommand.Command ,并将其绑定到我的视图模型中名为 SelectionChangedCommand 的 RelayCommand
<强> MainPage.xaml中强>
<GridView
x:Name="itemGridView"
IsItemClickEnabled="True"
ItemsSource="{Binding Timesheets}"
ItemTemplate="{StaticResource TimesheetTemplate}"
Margin="10"
Grid.Column="0"
SelectionMode="Multiple"
helpers:ItemClickCommand.Command="{Binding NavigateTimesheetCommand}"
helpers:SelectionChangedCommand.Command="{Binding SelectionChangedCommand}
"RenderTransformOrigin="0.738,0.55" >
</GridView>
然后我在帮助器名称空间下添加了 SelectionChangedCommand 帮助程序类,将 SelectionChanged 事件转换为 ICommand
namespace TimesheetManager.Helpers
{
public class SelectionChangedCommand
{
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof(ICommand),
typeof(SelectionChangedCommand), new PropertyMetadata(null,
OnCommandPropertyChanged));
public static void SetCommand(DependencyObject d, ICommand value)
{
d.SetValue(CommandProperty, value);
}
public static ICommand GetCommand(DependencyObject d)
{
return (ICommand)d.GetValue(CommandProperty);
}
private static void OnCommandPropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var control = d as ListViewBase;
if (control != null)
control.SelectionChanged += OnSelectionChanged;
}
private static void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var control = sender as ListViewBase;
var command = GetCommand(control);
if (command != null && command.CanExecute(e))
command.Execute(e);
}
}
}
这会将从 ListViewBase (我们的gridview)继承的任何控件的 SelectionChanged 事件绑定到名为 OnSelectionChanged 的方法。 OnSelectionChanged 随后将 SelectionChangedEventArgs 从控件传递到XAML中的 RelayCommand 绑定。
最后在 MainViewModel 中,我处理 RelayCommand 并设置 IsSelected 标记:
<强> MainViewModel:强>
private RelayCommand<object> _selectionChangedCommand;
/// <summary>
/// Gets the SelectionChangedCommand.
/// </summary>
public RelayCommand<object> SelectionChangedCommand
{
get
{
return _selectionChangedCommand ?? (_selectionChangedCommand = new RelayCommand<object>
((param) => ExecuteSelectionChangedCommand(param)));
}
}
private void ExecuteSelectionChangedCommand(object sender)
{
var x = sender as SelectionChangedEventArgs;
foreach (var item in x.AddedItems)
((TimesheetViewModel)item).IsSelected = true;
foreach (var item in x.RemovedItems)
((TimesheetViewModel)item).IsSelected = false;
}
我知道有相当数量的演员正在进行,但我们仅限于 ICommand 界面。
希望这有帮助。