첫 번째 열이 텍스트 열이고 두 번째 열이 CheckBox 열인 DataGrid가 있습니다. 확인란을 클릭하면 원하는 것입니다. 확인해야합니다.
그러나 선택하려면 두 번의 클릭이 필요합니다. 첫 번째 클릭의 경우 셀이 선택되고 두 번째 클릭의 경우 확인란이 선택됩니다. 한 번의 클릭으로 확인란을 선택 / 선택 취소하는 방법.
WPF 4.0을 사용하고 있습니다. DataGrid의 열은 자동 생성됩니다.
첫 번째 열이 텍스트 열이고 두 번째 열이 CheckBox 열인 DataGrid가 있습니다. 확인란을 클릭하면 원하는 것입니다. 확인해야합니다.
그러나 선택하려면 두 번의 클릭이 필요합니다. 첫 번째 클릭의 경우 셀이 선택되고 두 번째 클릭의 경우 확인란이 선택됩니다. 한 번의 클릭으로 확인란을 선택 / 선택 취소하는 방법.
WPF 4.0을 사용하고 있습니다. DataGrid의 열은 자동 생성됩니다.
답변:
한 번의 클릭으로 DataGrid 확인란의 경우 일반 확인란 컨트롤을 내부에 DataGridTemplateColumn
넣고 설정할 수 UpdateSourceTrigger=PropertyChanged
있습니다.
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=IsSelected, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
DataGridTemplateColumn.CellTemplate
함께 사용할 수 있으며 작동합니다! @ weidian-huang 의 대답 은 그 점을 이해하는 데 도움이되었습니다. 감사합니다!
나는 다음 스타일로 이것을 해결했다.
<Style TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="IsEditing" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
물론 특정 열에 맞게이를 더 조정할 수 있습니다 ...
첫째, 나는 이것이 꽤 오래된 질문이라는 것을 알고 있지만 여전히 시도하고 답할 것이라고 생각했습니다.
나는 며칠 전에 같은 문제가 있었고 놀랍게도 짧은 해결책을 찾았습니다 ( 이 블로그 참조 ). 기본적으로 DataGridCheckBoxColumn
XAML 의 정의를 다음으로 바꾸면됩니다.
<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 열광의 눈에 상태를 유지하는 데 도움이됩니다.).
확인하려면 콘스탄틴 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
자동 생성 된 모든 확인란 열을 "단일 클릭"으로 편집 할 수 있습니다.
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;
}
나는이 제안들과 다른 사이트에서 찾은 많은 다른 것들을 시도했지만 그중 어느 것도 나를 위해 일하지 않았습니다. 결국 다음과 같은 솔루션을 만들었습니다.
내 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 컨트롤이 포함되어 있는지 확인합니다. 이 경우 않습니다 , 우리는 그 체크 박스 초점을 설정합니다 그것의 가치 토글을 .
이것은 나에게 효과가있는 것으로 보이며 훌륭하고 쉽게 재사용 가능한 솔루션입니다.
이 작업을 수행하려면 코드를 작성 해야 한다는 점에 실망합니다 . WPF에서 행을 편집 모드로 전환하는 데 사용하기 때문에 첫 번째 마우스 클릭 (DataGrid의 CheckBox에서)이 "무시"된다는 설명은 논리적으로 들릴 수 있지만 실제 환경에서는 모든 실제 응용 프로그램의 작동 방식에 위배됩니다.
화면에 체크 박스가 표시되면 한 번 클릭하여 체크 / 체크 해제 할 수 있어야합니다. 이야기의 끝.
여기에는 훨씬 간단한 해결책이 있습니다.
<DataGridTemplateColumn MinWidth="20" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<CheckBox VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
DataGridCheckBoxColumn
구현 하는 데 사용 하는 경우 첫 번째 클릭은 초점을 맞추고 두 번째 클릭은 확인하는 것입니다.
그러나 DataGridTemplateColumn
구현에 사용 하려면 한 번만 클릭하면됩니다.
사용 DataGridComboboxBoxColumn
과 구현 의 차이점 DataGridTemplateColumn
도 비슷합니다.
나는 이것을 해결했다.
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Viewbox Height="25">
<CheckBox IsChecked="{Binding TheProperty, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
</Viewbox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
클릭 한 번으로 활성화 된 체크 박스!
에 자료 짐 아도르노의 대답과 자신의 게시물에 대한 의견이은과 솔루션입니다 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>
또 다른 간단한 해결책은이 스타일을 DataGridColumn에 추가하는 것입니다. 스타일의 본문은 비어있을 수 있습니다.
<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