아래와 같은 WPF XAML이 있습니다.
아래 소스에 대해서 현재 RelativeSource, FindAncestor, AncesstorType=‘System.Windows.Controls.DataGrid’, AncestorLevel=‘1’ 소스를 찾을 수 없습니다.
라는 에러가 발생하네요.
<DataGridTemplateColumn x:Name="dcChecked"
Width="Auto"
MinWidth="50">
<DataGridTemplateColumn.Header>
<unit:GdtCheckBox IsThreeState="False">
<unit:GdtCheckBox.IsChecked>
<Binding FallbackValue="False"
Path="DataContext.IsAllChecked"
UpdateSourceTrigger="PropertyChanged">
<Binding.RelativeSource>
<RelativeSource AncestorType="{x:Type unit:GdtDataGrid}" Mode="FindAncestor" />
</Binding.RelativeSource>
</Binding>
</unit:GdtCheckBox.IsChecked>
</unit:GdtCheckBox>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<unit:GdtCheckBox HorizontalAlignment="Center"
VerticalAlignment="Center"
IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
GdtCheckBox는 기존 CheckBox를 상속받는 CustomControl입니다.
DataGrid에 데이터가 있을 때는 에러가 발생하지 않지만, DataGrid에 바인딩된 ItemsSource의 Count가 0일 경우 , 데이터가 없으니까 랜더링할 Column이 없어서 그런지 RelativeSource 바인딩 에러가 발생 하는데요.
이럴 때 어떤 솔루션이 있을까요?
1 Like
al6uiz
August 7, 2023, 4:26am
2
올려주신 코드 내에서는 RelativeSource
바인딩으로 인한 오류가 발생할 부분은 없어 보입니다. GdtCheckBox
의 바인딩에 의해 오류가 났다면 AncesstorType
이 unit:GdtDataGrid
으로 표시됐을 겁니다.
AncestorType={x:Type DataGrid}
으로 설정된 바인딩이 있는지 확인해보시죠ㅎ
2 Likes
이미 질문을 올리기 전에 DataGrid와 GdtDataGrid 둘 다 AncestorType으로 지정했었습니다.
둘 다 ItemsSource에 데이터가 없을 경우 RelativeSource 바인딩 에러가 발생합니다.
1 Like
al6uiz
August 7, 2023, 5:00am
5
DataGrid
에서 DataGridColumnHeader
컨트롤은 VisualTree 상 DataGrid
컨트롤의 하위에 존재하고 ItemsSource
에 상관없이 항상 표시되므로 데이터의 유무에 따라 오류가 발생할 수 없습니다.
프로젝트 내 Style
또는 ControlTemplate
의 재정의나 IsCheckedAll
등의 구현 등 RelativeSource
를 지정한 다른 부분에서 오류가 발생한 것으로 추측됩니다.
1 Like
맞는 솔루션인지 모르겠지만 해결이 되어서 업데이트합니다.
<unit:GdtDataGrid Margin="{StaticResource DataGridBorderInterval}"
AutoGenerateColumns="False"
Background="{StaticResource DataGridAreaBackgroundBrush}"
BorderBrush="{StaticResource GdtDataGridBorderBrush}"
BorderThickness="1"
ColumnHeaderBackgroundBrush="{DynamicResource Theme_PopupDataViewColumnHeaderColorBrush}"
CornerRadius="{DynamicResource Theme_AllCornerRadius}"
ItemsSource="{Binding Source={StaticResource ItemsSort}}"
Visibility="{Binding Items.Count, Converter={cnvt:EmptyCollectionToVisibilityConverter}}">
...
<DataGrid.Columns>
<DataGridTemplateColumn x:Name="dcChecked"
Width="Auto"
MinWidth="50">
<DataGridTemplateColumn.Header>
<unit:GdtCheckBox IsThreeState="False">
<unit:GdtCheckBox.IsChecked>
<Binding FallbackValue="False"
Path="DataContext.IsAllChecked"
UpdateSourceTrigger="PropertyChanged">
<Binding.RelativeSource>
<RelativeSource AncestorType="{x:Type unit:GdtDataGrid}" Mode="FindAncestor" />
</Binding.RelativeSource>
</Binding>
</unit:GdtCheckBox.IsChecked>
</unit:GdtCheckBox>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<unit:GdtCheckBox HorizontalAlignment="Center"
VerticalAlignment="Center"
IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
</DataGrid.Columns>
</unit:GdtDataGrid>
형태는 위처럼 생겼었습니다.
이 DataGrid의 Items.Count가 0일 경우 보기 싫어서 아래 컨버터로 Items.Count가 0일 때 Visibility를 바꿨었습니다.
public sealed class EmptyCollectionToVisibilityConverter : ConverterMarkupExtension<EmptyCollectionToVisibilityConverter>
{
public override object? Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int count = System.Convert.ToInt32(value);
Visibility result = count == 0 ? Visibility.Collapsed : Visibility.Visible;
return result;
}
public override object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
여기서 아래 부분이 틀렸었네요.
Visibility result = count == 0 ? Visibility.Collapsed : Visibility.Visible;
저걸 Hidden으로 바꿔주면 바인딩에러가 발생하지 않고 정상 동작합니다.
Visibility result = count == 0 ? Visibility.Hidden : Visibility.Visible;
지금 프로젝트 마감 기간이라서 막히는 것을 제껴두고, 다른 일을 하다가… 혹시 몰라 바꿔본게 얻어 걸리게 되었습니다.
테스트 소스를 재현해서 올리려고 했었는데 그 전에 해결되었네요.
답변 주신 분들 모두 감사드립니다.
4 Likes