WPF Datagrid RowDetailsTemplate видимость, привязанная к свойству
Я использую WPF Datagrid с панелью RowDetails, где для параметра RowDetailsVisibilityMode установлено значение "VisibleWhenSelected" и SelectionMode = "Extended", чтобы можно было выбрать несколько строк и, следовательно, отобразить RowDetails, как показано ниже:
<dg:DataGrid x:Name="MyGrid"
ItemsSource="{Binding Path=MyItems}"
AutoGenerateColumns="True"
SelectionMode="Extended"
RowDetailsVisibilityMode="VisibleWhenSelected">
<dg:DataGrid.RowDetailsTemplate>
<DataTemplate>
<TextBlock Text="Further Details..."/>
</DataTemplate>
</dg:DataGrid.RowDetailsTemplate>
...
</dg:DataGrid>
К сожалению, для этого приложения неинтуитивно отображать данные о строках в "выбранных" строках, клиент хотел бы установить флажок в ряду строк для отображения панели RowDetails, а также прокрутить сетку, выбрав другую строк. Другими словами, исправьте строки, отображающие RowDetails, независимо от того, что происходит в DataGrid.
Таким образом, теперь прокрутка вокруг закрывает открытые RowDetailsPanes. Мне бы хотелось сделать флажок в одном из столбцов и привязать видимость панели RowDetails к этому свойству, но я не могу понять, как это сделать. Проблема заключается только в том, что RowDetailsPane работает только с выбором строки (ов) в datagrid - может ли она быть расширена каким-то образом для работы с собственностью по моему выбору?
Спасибо заранее,
Будет ли
Ответы
Ответ 1
Глядя на исходный код инструментария WPF, каждый DataGridRow имеет свойство DetailsVisibility.
Я положил кнопку (только для тестирования) в первом столбце.
<toolkit:DataGridTemplateColumn>
<toolkit:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="buttonDetails" Content="Hello" ButtonBase.Click="Details_Click" />
</DataTemplate>
</toolkit:DataGridTemplateColumn.CellTemplate>
</toolkit:DataGridTemplateColumn>
Когда кнопка нажата, найдите щелкнув строку и переключите свойство.
private void Details_Click(object sender, RoutedEventArgs e)
{
try
{
// the original source is what was clicked. For example
// a button.
DependencyObject dep = (DependencyObject)e.OriginalSource;
// iteratively traverse the visual tree upwards looking for
// the clicked row.
while ((dep != null) && !(dep is DataGridRow))
{
dep = VisualTreeHelper.GetParent(dep);
}
// if we found the clicked row
if (dep != null && dep is DataGridRow)
{
// get the row
DataGridRow row = (DataGridRow)dep;
// change the details visibility
if (row.DetailsVisibility == Visibility.Collapsed)
{
row.DetailsVisibility = Visibility.Visible;
}
else
{
row.DetailsVisibility = Visibility.Collapsed;
}
}
}
catch (System.Exception)
{
}
}
Я не исследовал это с помощью привязки данных.
Ответ 2
Использование чистого XAML (+ a конвертер):
XAML:
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<ToggleButton
IsChecked="{Binding Path=DetailsVisibility,
RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}},
Converter={StaticResource _VisibilityToNullableBooleanConverter}}"
/>
</DataTemplate>
</DataGrid.RowHeaderTemplate>
Преобразователь
public class VisibilityToNullableBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Visibility)
{
return (((Visibility)value) == Visibility.Visible);
}
else
{
return Binding.DoNothing;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool?)
{
return (((bool?)value) == true ? Visibility.Visible : Visibility.Collapsed);
}
else if (value is bool)
{
return (((bool)value) == true ? Visibility.Visible : Visibility.Collapsed);
}
else
{
return Binding.DoNothing;
}
}
}
Ответ 3
Если вы используете (отличную) библиотеку Lambda Converters, вы можете сохранить дополнительный класс. Этот конвертер использует 2 лямбда-выражения, первый для Convert, второй для ConvertBack, например:
public static readonly IValueConverter VisibilityToBoolean =
ValueConverter.Create<Visibility, bool>(
(e => e.Value == Visibility.Visible),
(e => e.Value ? Visibility.Visible : Visibility.Collapsed));
Затем XAML выглядит следующим образом (обратите внимание, что при использовании этого подхода нет необходимости использовать StaticResources):
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<ToggleButton>
<ToggleButton.IsChecked>
<Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGridRow}}" Path="DetailsVisibility"
Converter="{x:Static lc40:Converters.VisibilityToBoolean}"/>
</ToggleButton.IsChecked>
</ToggleButton>
</DataTemplate>
</DataGrid.RowHeaderTemplate>
Конвертеры Lambda доступны здесь:
https://github.com/michael-damatov/lambda-converters