2013-02-26 4 views
4

나는 DataGrid이며 선택한 행과 포커스가있는 행을 동기화하려고합니다. 즉, 집중된 행이 변경된 경우 선택한 행이 변경되고 선택된 행이 변경되면 포커스가있는 행이됩니다.DataGridRow 포커스 및 선택 항목을 동기화 된 상태로 유지하는 방법?

다음 XAML이 포함 된 WPF 창에서 포커스가있는 행과 선택한 행을 어떻게 동기화 할 수 있습니까? 나는 이것이 기본 동작입니다 생각으로 다음과 같은 이미지로

<Window x:Class="WpfApplication2.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 

    <Grid> 
     <Grid.Resources> 

      <x:Array x:Key="MyList" Type="sys:String" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib"> 
       <sys:String>Hello</sys:String> 
       <sys:String>World</sys:String> 
       <sys:String>World</sys:String> 
       <sys:String>World</sys:String> 
       <sys:String>World</sys:String> 
       <sys:String>World</sys:String> 
       <sys:String>World</sys:String> 
       <sys:String>World</sys:String> 
       <sys:String>World</sys:String> 
      </x:Array> 

      <Style TargetType="{x:Type DataGrid}"> 
       <Setter Property="AlternationCount" Value="2" /> 
       <Setter Property="AutoGenerateColumns" Value="False"/> 
      </Style> 

      <Style TargetType="{x:Type DataGridCell}"> 
       <Setter Property="Background" Value="Transparent"/> 
       <Setter Property="Focusable" Value="False"/> 
      </Style> 

      <Style TargetType="{x:Type DataGridRow}"> 
       <Setter Property="Focusable" Value="True"/> 
       <Style.Triggers> 
        <MultiTrigger> 
         <MultiTrigger.Conditions> 
          <Condition Property="AlternationIndex" Value="0"/> 
          <Condition Property="IsSelected" Value="False"/> 
         </MultiTrigger.Conditions> 
         <Setter Property="Background" Value="White"/> 
        </MultiTrigger> 
        <MultiTrigger> 
         <MultiTrigger.Conditions> 
          <Condition Property="AlternationIndex" Value="1"/> 
          <Condition Property="IsSelected" Value="False"/> 
         </MultiTrigger.Conditions> 
         <Setter Property="Background" Value="Gainsboro"/> 
        </MultiTrigger> 
        <Trigger Property="AlternationIndex" Value="1"> 
         <Setter Property="Background" Value="Gainsboro"/> 
        </Trigger> 
        <Trigger Property="IsSelected" Value="True"> 
         <Setter Property="Background" Value="#BF228B22"/> 
         <Setter Property="BorderBrush" Value="ForestGreen"/> 
         <Setter Property="BorderThickness" Value="1"/> 
        </Trigger> 
       </Style.Triggers> 
      </Style> 

     </Grid.Resources> 

     <DataGrid ItemsSource="{StaticResource MyList}"> 
      <DataGrid.Columns> 
       <DataGridTextColumn Header="Name" Binding="{Binding}" Width="*"/> 
      </DataGrid.Columns> 
     </DataGrid> 

    </Grid> 

</Window> 

, 당신은 빨간색으로 포커스 사각형과 녹색에서 선택한 행이 명확하게 동기화되지 않은 것을 볼 수 있습니다. 내가 원했던 것은 항상 동일한 것입니다. 즉, SelectedRow는 항상 Focused이고 FocusedRow는 항상 Selected입니다.

enter image description here

답변

2

DataGrid에 내부 포커스 변경 및 선택 변경 이벤트를 수신하기 위해 연결된 속성을 사용해보십시오. 이러한 상황이 발생하면 선택 또는 포커스를 변경하여 적절하게 대응할 수 있습니다.

다음은 몇 가지 예제 코드입니다. DataGridAttachment 클래스에 특히주의하십시오. 그것이 연결된 속성이 정의되고 로직이 포커스 및 선택 변경 이벤트에 반응하는 곳입니다.

MainWindow.xaml

<Window x:Class="_15098869.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:_15098869" 
    Title="MainWindow" 
    Width="525" 
    Height="350"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <DataGrid Name="DataGrid" 
       ItemsSource="{Binding Path=Items}" 
       local:DataGridAttachment.SyncSelectionWithFocus="True" /> 
    <Button Grid.Row="1" 
      Click="MoveSelectionButtonOnClick" 
      Content="Move Selection" /> 
</Grid> 

MainWindow.xaml.cs를 (코드 숨김)

using System.Collections.ObjectModel; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Controls.Primitives; 

namespace _15098869 
{ 
    /// <summary> 
    ///  Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      DataContext = this; 

      Items = new ObservableCollection<DemoItem>(); 
      Items.Add(new DemoItem {FirstName = "John", LastName = "Doe"}); 
      Items.Add(new DemoItem {FirstName = "Jane", LastName = "Doe"}); 
      Items.Add(new DemoItem {FirstName = "Bob", LastName = "Doe"}); 
     } 

     public ObservableCollection<DemoItem> Items { get; private set; } 

     public void MoveSelectionButtonOnClick(object sender, RoutedEventArgs e) 
     { 
      var max = DataGrid.Items.Count - 1; 
      DataGrid.SelectedIndex = DataGrid.SelectedIndex == max ? 0 : DataGrid.SelectedIndex + 1; 
     } 
    } 

    public class DemoItem 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
    } 

    public static class DataGridAttachment 
    { 
     public static readonly DependencyProperty SyncSelectionWithFocusProperty = 
      DependencyProperty.RegisterAttached("SyncSelectionWithFocus", typeof (bool), typeof (DataGridAttachment), new PropertyMetadata(default(bool), SyncSelectionWithFocusChanged)); 

     private static void SyncSelectionWithFocusChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
     { 
      var dataGrid = dependencyObject as DataGrid; 
      if (dataGrid == null) return; 

      var shouldSync = GetSyncSelectionWithFocus(dataGrid); 

      if (shouldSync) 
      { 
       dataGrid.AddHandler(UIElement.GotFocusEvent, new RoutedEventHandler(DataGridOnGotFocus)); 
       dataGrid.AddHandler(Selector.SelectionChangedEvent, new SelectionChangedEventHandler(DataGridOnSelectionChanged)); 
      } 
     } 

     private static void DataGridOnGotFocus(object sender, RoutedEventArgs e) 
     { 
      var dataGrid = sender as DataGrid; 
      var element = e.OriginalSource as DataGridCell; 

      if (dataGrid == null || element == null) return; 
      dataGrid.SelectedItem = element.DataContext; 
     } 

     private static void DataGridOnSelectionChanged(object sender, SelectionChangedEventArgs e) 
     { 
      var dataGrid = sender as DataGrid; 

      if (dataGrid == null) return; 

      if (!dataGrid.IsKeyboardFocusWithin) 
      { 
       dataGrid.Focus(); 
      } 
     } 

     public static void SetSyncSelectionWithFocus(DataGrid element, bool value) 
     { 
      element.SetValue(SyncSelectionWithFocusProperty, value); 
     } 

     public static bool GetSyncSelectionWithFocus(DataGrid element) 
     { 
      return (bool) element.GetValue(SyncSelectionWithFocusProperty); 
     } 
    } 
} 
+0

감사합니다. 나는 이것을 곧 시도 할 것이다. 나는이 길을 시작하고 있었지만 먼저 물어볼 것이라고 생각했다. – Jim

관련 문제