WPF DataGrid에서 한 번 클릭 확인란을 선택하는 방법은 무엇입니까?
첫 번째 열이 텍스트 열이고 두 번째 열이 CheckBox 열인 DataGrid가 있습니다. 확인란을 클릭하면 원하는 것입니다. 확인해야합니다.
그러나 선택하려면 두 번의 클릭이 필요합니다. 첫 번째 클릭의 경우 셀이 선택되고 두 번째 클릭의 경우 확인란이 선택됩니다. 한 번의 클릭으로 확인란을 선택 / 선택 취소하는 방법.
WPF 4.0을 사용하고 있습니다. DataGrid의 열은 자동 생성됩니다.
한 번의 클릭으로 DataGrid 확인란의 경우 일반 확인란 컨트롤을 내부에 DataGridTemplateColumn넣고 설정할 수 UpdateSourceTrigger=PropertyChanged있습니다.
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=IsSelected, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
나는 다음 스타일로 이것을 해결했다.
<Style TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="IsEditing" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
물론 특정 열에 대해 이것을 더 조정할 수 있습니다 ...
첫째, 나는 이것이 꽤 오래된 질문이라는 것을 알고 있지만 여전히 시도하고 답할 것이라고 생각했습니다.
나는 며칠 전에 같은 문제가 있었고 놀랍게도 짧은 해결책을 찾았습니다 ( 이 블로그 참조 ). 기본적으로 DataGridCheckBoxColumnXAML 의 정의를 다음으로 바꾸면됩니다.
<DataGridTemplateColumn Header="MyCheckBoxColumnHeader">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="{Binding Path=MyViewModelProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
이 솔루션의 장점은 명백합니다. XAML 전용입니다. 따라서 추가 UI 로직으로 코드 백에 부담을주지 않도록 효과적으로 억제하고 MVVM 열광의 눈에 상태를 유지하는 데 도움이됩니다.
Goblin의 답변에서 참조 된 블로그를 기반으로하지만 .NET 4.0 및 행 선택 모드에서 작동하도록 수정되었습니다.
또한 편집 모드로 들어가서 한 번의 클릭 또는 텍스트 입력시 드롭 다운을 표시하여 DataGridComboBoxColumn 편집 속도를 높입니다.
XAML :
<Style TargetType="{x:Type DataGridCell}">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown" />
<EventSetter Event="PreviewTextInput" Handler="DataGridCell_PreviewTextInput" />
</Style>
코드 숨김 :
private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DataGridCell cell = sender as DataGridCell;
GridColumnFastEdit(cell, e);
}
private void DataGridCell_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
DataGridCell cell = sender as DataGridCell;
GridColumnFastEdit(cell, e);
}
private static void GridColumnFastEdit(DataGridCell cell, RoutedEventArgs e)
{
if (cell == null || cell.IsEditing || cell.IsReadOnly)
return;
DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
if (dataGrid == null)
return;
if (!cell.IsFocused)
{
cell.Focus();
}
if (cell.Content is CheckBox)
{
if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
{
if (!cell.IsSelected)
cell.IsSelected = true;
}
else
{
DataGridRow row = FindVisualParent<DataGridRow>(cell);
if (row != null && !row.IsSelected)
{
row.IsSelected = true;
}
}
}
else
{
ComboBox cb = cell.Content as ComboBox;
if (cb != null)
{
//DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
dataGrid.BeginEdit(e);
cell.Dispatcher.Invoke(
DispatcherPriority.Background,
new Action(delegate { }));
cb.IsDropDownOpen = true;
}
}
}
private static T FindVisualParent<T>(UIElement element) where T : UIElement
{
UIElement parent = element;
while (parent != null)
{
T correctlyTyped = parent as T;
if (correctlyTyped != null)
{
return correctlyTyped;
}
parent = VisualTreeHelper.GetParent(parent) as UIElement;
}
return null;
}
확인하려면 콘스탄틴 Salavatov의 응답 으로 작업을 AutoGenerateColumns받는 이벤트 처리기를 추가, DataGrid의 AutoGeneratingColumn다음 코드 :
if (e.Column is DataGridCheckBoxColumn && !e.Column.IsReadOnly)
{
var checkboxFactory = new FrameworkElementFactory(typeof(CheckBox));
checkboxFactory.SetValue(FrameworkElement.HorizontalAlignmentProperty, HorizontalAlignment.Center);
checkboxFactory.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center);
checkboxFactory.SetBinding(ToggleButton.IsCheckedProperty, new Binding(e.PropertyName) { UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
e.Column = new DataGridTemplateColumn
{
Header = e.Column.Header,
CellTemplate = new DataTemplate { VisualTree = checkboxFactory },
SortMemberPath = e.Column.SortMemberPath
};
}
이렇게하면 DataGrid자동 생성 된 모든 확인란 열을 "단일 클릭"으로 편집 할 수 있습니다.
나는이 제안들과 다른 사이트에서 찾은 많은 다른 것들을 시도했지만 그중 어느 것도 나를 위해 일한 적이 없습니다. 결국 다음과 같은 솔루션을 만들었습니다.
내 DataGrid 상속 컨트롤을 만들고이 코드를 추가했습니다.
public class DataGridWithNavigation : Microsoft.Windows.Controls.DataGrid
{
public DataGridWithNavigation()
{
EventManager.RegisterClassHandler(typeof(DataGridCell),
DataGridCell.PreviewMouseLeftButtonDownEvent,
new RoutedEventHandler(this.OnPreviewMouseLeftButtonDown));
}
private void OnPreviewMouseLeftButtonDown(object sender, RoutedEventArgs e)
{
DataGridCell cell = sender as DataGridCell;
if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
{
DependencyObject obj = FindFirstControlInChildren(cell, "CheckBox");
if (obj != null)
{
System.Windows.Controls.CheckBox cb = (System.Windows.Controls.CheckBox)obj;
cb.Focus();
cb.IsChecked = !cb.IsChecked;
}
}
}
public DependencyObject FindFirstControlInChildren(DependencyObject obj, string controlType)
{
if (obj == null)
return null;
// Get a list of all occurrences of a particular type of control (eg "CheckBox")
IEnumerable<DependencyObject> ctrls = FindInVisualTreeDown(obj, controlType);
if (ctrls.Count() == 0)
return null;
return ctrls.First();
}
public IEnumerable<DependencyObject> FindInVisualTreeDown(DependencyObject obj, string type)
{
if (obj != null)
{
if (obj.GetType().ToString().EndsWith(type))
{
yield return obj;
}
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
foreach (var child in FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type))
{
if (child != null)
{
yield return child;
}
}
}
}
yield break;
}
}
이 모든 것이 무엇입니까?
데이터 그리드에서 셀을 클릭 할 때마다 셀에 CheckBox 컨트롤이 포함되어 있는지 확인합니다. 이 경우 않습니다 , 우리는 그 체크 박스 초점을 설정합니다 그것의 가치 토글을 .
This seems to work for me, and is a nice, easily reusable solution.
It is disappointing that we need to write code to do this though. The explanation that the first mouse click (on a DataGrid's CheckBox) is "ignored" as WPF uses it to put the row into Edit mode might sound logical, but in the real-world, this goes against the way every real application works.
If a user sees a checkbox on their screen, they should be able to click on it once to tick/untick it. End of story.
There is a much simpler solution here.
<DataGridTemplateColumn MinWidth="20" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<CheckBox VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
If you use DataGridCheckBoxColumn to implement, first click is to focus, second click is to check.
But using DataGridTemplateColumn to implement needs one click only.
The difference of using DataGridComboboxBoxColumn and implementation by DataGridTemplateColumn is also similar.
I solved with this:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Viewbox Height="25">
<CheckBox IsChecked="{Binding TheProperty, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
</Viewbox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
The checkbox active on single click!
Base on Jim Adorno answer and comments on his post, this is solution with MultiTrigger:
<Style TargetType="DataGridCell">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsReadOnly" Value="False" />
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="IsEditing" Value="True" />
</MultiTrigger>
</Style.Triggers>
</Style>
Yet another simple solution is to add this style to your DataGridColumn.The body of your style can be empty.
<DataGridCheckBoxColumn>
<DataGridCheckBoxColumn.ElementStyle>
<Style TargetType="CheckBox">
</Style>
</DataGridCheckBoxColumn.ElementStyle>
</DataGridCheckBoxColumn>
<Style x:Key="StilCelula" TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="IsEditing"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Converter={StaticResource CheckBoxColumnToEditingConvertor}}" />
</Trigger>
</Style.Triggers>
<Style>
Imports System.Globalization
Public Class CheckBoxColumnToEditingConvertor
Implements IValueConverter
Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As CultureInfo) As Object Implements IValueConverter.Convert
Try
Return TypeOf TryCast(value, DataGridCell).Column Is DataGridCheckBoxColumn
Catch ex As Exception
Return Visibility.Collapsed
End Try
End Function
Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
Throw New NotImplementedException()
End Function
End Class
'Programming' 카테고리의 다른 글
| 다른 테이블로 데이터 복사 (0) | 2020.06.29 |
|---|---|
| 오늘 3 개월 전에 JavaScript로 날짜를 어떻게 계산합니까? (0) | 2020.06.29 |
| 클래스 상수에 액세스 (0) | 2020.06.29 |
| 숫자 (0-9) 만 허용하고 문자는 허용하지 않는 정규식 (0) | 2020.06.29 |
| 소셜 네트워크에서 활동 스트림을 구현하는 방법 (0) | 2020.06.28 |