我有一个WPF DataGrid
,其中有18列,每列上方都有一个TextBox
,因此我可以过滤该列。
每个TextBox
将Width
绑定到列的ActualWidth
。
<StackPanel Grid.Row="0" Orientation="Horizontal">
<TextBox Width="{Binding Path=ActualWidth, ElementName=Column1}" Text="{Binding FilterFirstName}"/>
<TextBox Width="{Binding Path=ActualWidth, ElementName=Column2}" Text="{Binding FilterLastName}"/>
<TextBox Width="{Binding Path=ActualWidth, ElementName=Column3}" Text="{Binding FilterAge}"/>
<!-- 15 more -->
</StackPanel>
<DataGrid x:Name="dataGridUsers" Grid.Row="1" ItemsSource="{Binding Users}">
<DataGrid.Columns>
<DataGridTextColumn x:Name="Column1" Width="*" Binding="{Binding FirstName}"/>
<DataGridTextColumn x:Name="Column2" Width="*" Binding="{Binding LastName}"/>
<DataGridTextColumn x:Name="Column3" Width="*" Binding="{Binding Age}"/>
<!-- 15 more -->
</DataGrid.Columns>
</DataGrid>
我知道我可以像这样将TextBox
Text
绑定到List<string>
上:
<TextBox Width="{Binding Path=ActualWidth, ElementName=Column1}" Text="{Binding Filters[0]}"/>
<TextBox Width="{Binding Path=ActualWidth, ElementName=Column2}" Text="{Binding Filters[1]}"/>
<TextBox Width="{Binding Path=ActualWidth, ElementName=Column3}" Text="{Binding Filters[2]}"/>
我想将Width
的{{1}}绑定到该列的TextBox
,如下所示:
ActualWidth
因为这样我可以使用<TextBox Width="{Binding Path=ActualWidth, Source=dataGridUsers.Columns[0]}" Text="{Binding Filters[0]}"/>
<TextBox Width="{Binding Path=ActualWidth, Source=dataGridUsers.Columns[1]}" Text="{Binding Filters[1]}"/>
<TextBox Width="{Binding Path=ActualWidth, Source=dataGridUsers.Columns[2]}" Text="{Binding Filters[2]}"/>
代替ItemsControl
,但是这种方式行不通。
还有其他方法可以实现这一目标吗?
答案 0 :(得分:2)
您无法绑定到DataGrid
列属性,因为它们仅在逻辑树中,而不在可视树中。
这样做的唯一方法是更改DataGridTextColumn.HeaderTemplate
并使用其中的过滤器DataTemplate
创建一个新的TextBox
。
答案 1 :(得分:1)
这样做确实可以绑定到t
的列
DataGrid
但这对您想要实现的目标无效。在运行时对列进行重新排序后,该顺序将不再与TextBoxes的顺序匹配。所以你也必须重新排序。
注意:DataGridColumn.DisplayIndex
返回<TextBox Width="{Binding Columns[0].ActualWidth, ElementName=dataGridUsers}" />
中的当前索引。
更好的方法和推荐的方法是通过更改DataGrid
答案 2 :(得分:0)
ItemsControl
和TextBox
来过滤DataGrid列可以像这样使用ItemsControl
并绑定到DataGrid.Columns
:
<ItemsControl Grid.Row="0" ItemsSource="{Binding Path=Columns, ElementName=dataGrid}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Width="{Binding ActualWidth}">
<TextBox.Resources>
<local:ListIndexToValueConverter x:Key="listIndexToValueConverter"/>
</TextBox.Resources>
<TextBox.Text>
<MultiBinding Converter="{StaticResource listIndexToValueConverter}" UpdateSourceTrigger="PropertyChanged">
<Binding Path="DataContext.Filters" ElementName="userControl"/>
<Binding Path="DisplayIndex"/>
</MultiBinding>
</TextBox.Text>
</TextBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<DataGrid x:Name="dataGrid" Grid.Row="1" ItemsSource="{Binding Users}">
<DataGrid.Columns>
<DataGridTextColumn DisplayIndex="0" Width="*" Binding="{Binding FirstName}"/>
<DataGridTextColumn DisplayIndex="1" Width="*" Binding="{Binding LastName}"/>
<DataGridTextColumn DisplayIndex="2" Width="*" Binding="{Binding Age}"/>
</DataGrid.Columns>
</DataGrid>
因为您将ItemsControl.ItemsSource
设置为DataGrid.Columns
而不是DataContext.Filters
,所以必须设置DataGridColumn.DisplayIndex
并使用IMultiValueConverter
才能访问{{1} }:
DataContext.Filters
ViewModel:
public class ListIndexToValueConverter : IMultiValueConverter
{
private IList _list;
private int _index;
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length < 2)
return Binding.DoNothing;
if (values[0] is IList && values[1] is int)
{
_list = (IList)values[0];
_index = (int)values[1];
return _list[_index];
}
return Binding.DoNothing;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
_list[_index] = value;
return new object[] { Binding.DoNothing, Binding.DoNothing };
}
}