2013-08-21 5 views
2

길었습니다. 알고 싶지만 나와 함께하시기 바랍니다.Windows App Store에서 선택한 항목 반복 Gridview

MVVM 라이트 프레임 워크를 사용하여 MVVM 라이트 샘플의 Laurent Bugnion의 "MyFriends"프로그램과 매우 유사한 Windows 앱 스토어 프로그램을 만들었습니다.

그는 자신의 프로그램에서 gridview의 SelectedItem 속성을 사용하여 어떤 항목이 선택된 항목인지 추적합니다.

문제는 사용자가 GridView에서 여러 항목을 선택한 다음 응용 프로그램 모음의 단추를 사용하여 작업 할 수 있다는 것입니다. 이를 위해 SelectedItem은 작동하지 않습니다.

누구든지 다중 선택 GridView에서이 작업을 수행하는 방법을 알고 있습니까? WPF의 일부 기사를 기반으로 GridViewItem의 IsSelected 속성을 시도했지만 작동하지 않는 것 같습니다. SelectedTimesheets getter는 호출 될 때 항상 비어있게됩니다.

<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)); 
      } 

     } 
    } 
} 

에서 MainPage.xaml이 (아이 TimesheetViewModel 관찰 수집과 MainViewModel에 바인딩) : 여기에 지금까지 무엇을 가지고

TimesheetViewModel :

public class TimesheetViewModel: ViewModelBase 
{ 

    public bool IsSelected { get; set; } 

    public Timesheet Model 
    { 
     get; 
     private set; 
    } 

    public TimesheetViewModel(Timesheet model) 
    { 
     Model = model; 

    } 
} 

내가 수동에 isSelected 속성을 설정하면, SelectedTimesheets 람다가 작동하므로 문제는 XAML을 IsSelected 속성에 바인딩하는 것입니다.

도움을 주시면 감사하겠습니다.

답변

1

@ Jerry-Nixon-MSFT의 답변 덕분에 그를 다시 생각하게되었습니다 (그에게 감사드립니다). 나는 다음 해결책을 제시했습니다.

는 첫째로 나는 을 SelectionChangedCommand.Command 내보기 모델

MainPage에서 SelectionChangedCommand라는 RelayCommand에 결합 된 새로운 도우미 메서드를 허용하도록 XAML을 변경했습니다.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> 

나는 다음 이는 어떤의 이벤트 인 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); 

     } 
    } 

} 

이벤트 인 selectionchanged 번역 내 도우미 네임 스페이스 아래 SelectionChangedCommand 헬퍼 클래스를 추가 에서 상속받은 컨트롤 ListViewBase (우리의 gridview) to OnSelectionChanged이라는 메서드가 있습니다. OnSelectionChangedSelectionChangedEventArgs을 컨트롤에서 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 인터페이스로 제한됩니다.

희망이 도움이됩니다.

+0

꽤 오래 전 게시되었지만 몇 가지 사항에 대해 궁금합니다. 1) GridView에서 상속 한 사용자 지정 그리드 뷰를 만드는 경우 GridView 컨트롤의 일부로이 기능을 구현할 방법이 없습니까? 2) SelectionCommand가 viewmodel에서 트리거되면 JerryNixon-MSFT가 게시 한 메소드를 사용하면 항상 선택된 항목의 총 수가 잘못 표시됩니다. 선택은 항상 뒤떨어져있는 것 같습니다. 어떤 아이디어? – Thierry

6

확실히, 나는 당신이 의미하는 것을 안다. 너무 나쁘다는 것은 automagic이 아니지만 그렇지 않습니다. 이 솔루션에는 GridView을 상속하는 간단한 사용자 지정 GridView이 포함됩니다. .

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

여기 (슈퍼가-간체) 뷰 모델입니다 :

여기

이 XAML의 : 너무 미친 아무것도, 즉 당신이에 침몰 할 경우 여기없는 코드입니다, 난 그냥 테스트

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 :

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입니다.

행운을 빈다.

+0

ViewModel에서 ObservableCollection 을 선택합니다. –

+0

Jerry에게 고맙다. 여기 코드를 도우미 메서드로 추출하여 다시 게시 할 수 있는지 찾고 있습니다. – Sico

+0

답변을 추가했습니다. 도우미 클래스를 사용하도록 다시 작성되었습니다. 감사. – Sico

관련 문제