2010-04-10 6 views
14

다중 선택할 수있는 DataGrid가 있습니다. 뷰 모델에서 선택을 변경해야합니다. 그러나 SelectedItems 속성은 읽기 전용이며 viewmodel의 속성에 직접 바인딩 할 수 없습니다. 그렇다면 선택이 변경되었다는 신호에 어떻게 신호를 보내야합니까?WPF DataGrid 다중 선택 바인딩

+0

도 참조 http://stackoverflow.com/questions/1579700/wpf-toolkit-datagrid-multi-select-how-to-get-selecteditems-out –

답변

6

나는 많은 DataGrid 함께 일하지 않은,하지만 ListView 작동 한 기술은 개별 ListViewItemIsSelected 속성에 바인딩하는 것입니다. 목록의 각 개체에 대해이 값을 true으로 설정하면 선택한 개체가 선택됩니다.

어쩌면 DataGrid의 행을 나타내는 개체도 IsSelected 속성을 가지며이 방법으로도 사용할 수 있습니까?

17

Andy가 정확합니다. DataGridRow.IsSelected은 ViewModel에서 선택을 제어하기 위해 데이터 바인딩 될 수있는 종속성 속성입니다. 다음 예제 코드에서는이 방법을 보여줍니다

<Window x:Class="DataGridMultiSelectSample.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:tk="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel> 
     <tk:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" EnableRowVirtualization="False"> 
      <tk:DataGrid.Columns> 
       <tk:DataGridTextColumn Header="Value" Binding="{Binding Value}" /> 
      </tk:DataGrid.Columns> 
      <tk:DataGrid.RowStyle> 
       <Style TargetType="tk:DataGridRow"> 
        <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 
       </Style> 
      </tk:DataGrid.RowStyle> 
     </tk:DataGrid> 
     <Button Content="Select Even" Click="Even_Click" /> 
     <Button Content="Select Odd" Click="Odd_Click" /> 
    </StackPanel> 
</Window> 

using System.ComponentModel; 
using System.Windows; 

namespace DataGridMultiSelectSample 
{ 
    public partial class Window1 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
      DataContext = new[] 
           { 
            new MyViewModel {Value = "Able"}, 
            new MyViewModel {Value = "Baker"}, 
            new MyViewModel {Value = "Charlie"}, 
            new MyViewModel {Value = "Dog"}, 
            new MyViewModel {Value = "Fox"}, 
           }; 
     } 

     private void Even_Click(object sender, RoutedEventArgs e) 
     { 
      var array = (MyViewModel[]) DataContext; 
      for (int i = 0; i < array.Length; ++i) 
       array[i].IsSelected = i%2 == 0; 
     } 

     private void Odd_Click(object sender, RoutedEventArgs e) 
     { 
      var array = (MyViewModel[])DataContext; 
      for (int i = 0; i < array.Length; ++i) 
       array[i].IsSelected = i % 2 == 1; 
     } 
    } 

    public class MyViewModel : INotifyPropertyChanged 
    { 
     public string Value { get; set; } 

     private bool mIsSelected; 
     public bool IsSelected 
     { 
      get { return mIsSelected; } 
      set 
      { 
       if (mIsSelected == value) return; 
       mIsSelected = value; 
       if (PropertyChanged != null) 
        PropertyChanged(this, new PropertyChangedEventArgs("IsSelected")); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
    } 
} 

DataGrid 구성 요소에 EnableRowVirtualisation="False"을 설정해야합니다, 그렇지 않으면에 isSelected 바인딩이 호조 떨어지 위험이있다.

+0

적합합니다. 샘플 코드를 이용해 주셔서 감사합니다. –

+0

감사. 당신이'EnableRowVirtualisation = "False"를 예제에 추가하지 않았다면, 바인딩이 새로운 행에없는 버그가 있기를 바랍니다. –

3

얘들 아, 도와 줘서 고마워. 내 문제가 해결되었습니다. 나는이 문제가 새로운 WPF 개발자들에게 매우 보편적이라고 생각한다. 그래서 다른 누군가가 같은 종류의 문제를 겪을 경우에 대비하여 문제와 해결책을 더 자세히 설명 할 것이다.

문제 : 오디오 파일의 다중 선택 가능 데이터 격자가 있습니다. 그리드에는 여러 개의 열 머리글이 있습니다. 사용자는 여러 행을 여러 개 선택할 수 있습니다. 재생 버튼을 클릭하면 오디오 파일이 열 머리글 (A 열)의 순서로 재생됩니다. 재생이 시작되면 다중 선택이 지워지고 현재 재생중인 파일 만 강조 표시됩니다. 모든 파일에 대한 재생이 끝나면 다중 선택이 다시 표시됩니다. 재생은 뷰 모델에서 수행됩니다. 보시다시피 현재 두 가지 문제가 있습니다. 1)보기 모드에서 현재 재생중인 파일을 선택하는 방법과 2)보기 모드에서 재생이 완료되었다는 신호를 보내어 다중 선택을 다시 표시하는 방법.

해결 방법 : 첫 번째 문제를 해결하기 위해 뷰의 SelectedIndex 속성에 바인딩되어 현재 재생중인 파일을 선택하는 속성을 뷰 모델에 만들었습니다. 두 번째 문제를 해결하기 위해 뷰 모델에 부울 속성을 만들어 재생이 완료되었음을 나타냅니다. 뷰의 코드에서 나는 불린 프로퍼티의 PropertyChanged 이벤트를 구독했다. 이벤트 처리기에서보기의 SelectedItems 속성은 저장된 다중 선택 (SelectedItems의 내용이 목록에 저장되고 재생이 시작되면 SelectedItems가 지워짐)에서 다시 만들어집니다. 처음에는 SelectedItem을 다시 만드는 데 어려움이있었습니다. 문제는 다시 생성이 두 번째 스레드를 통해 시작되었다는 사실 때문이었습니다. WPF는이를 허용하지 않습니다. 이에 대한 해결책은 Dispatcher.Invoke()를 사용하여 주 스레드가 작업을 수행하도록하는 것입니다. 이것은 숙련 된 개발자에게는 매우 간단한 문제 일 수 있지만 초보자에게는 작은 문제입니다. 어쨌든, 다른 사람들로부터 많은 도움을.

2

MultiSelector 파생 클래스에서 SelectedItems를 사용하고 IList에서 Add, Remove, Clear 메서드를 사용하면 반환됩니다.

감사합니다, 로빈