通过 C# 访问 ListView 内的组合框
Access ComboBoxes inside a ListView via C#
我有一个包含 2 列的 ListView。第一列是一个简单的字符串。第二个模板设置为单个 ComboBox。行数和 ComboBox 的数量未知。
我的XAML:
<ListView Grid.Row="0" Name="listView" IsSynchronizedWithCurrentItem="True" SelectionMode="Single" Margin="10" ItemsSource="{Binding ImportColumns}">
<ListView.Resources>
<local:ListFilterMultiConverter x:Key="listFilterConverter" />
</ListView.Resources>
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="File column" DisplayMemberBinding="{Binding FileColumnHeader}"/>
<GridViewColumn Header="Worksheet column">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox VerticalAlignment="Center" DataContext="{Binding DataContext,RelativeSource={RelativeSource AncestorType={x:Type ListView}}}" SelectionChanged="ComboBox_SelectionChanged" SelectedIndex="0" >
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource listFilterConverter}">
<Binding Path="ListOfWorksheetColumns.UnselectedWorksheetColumns"/>
<Binding RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</ComboBox.ItemsSource>
</ComboBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
我需要知道第二列的组合框中的内容,以便第一列中的字符串可以与相应组合框的值相关联。问题是我只引用了第一列中的项目。
我的导入列class:
public class ImportColumn : BaseViewModel
{
public string FileColumnHeader { get; set; }
}
BaseViewModel class:
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
}
像您在此处所做的那样绑定 DataContext 是错误的,因为绑定的 DataContext 将是 ComboBox 上任何其他绑定的默认源。这会妨碍您,因为您希望能够绑定到真实数据上下文的属性,即行对象 ImportColumn
。
我们可以通过在多重绑定中使用与 DataContext 相同的 RelativeSource 来解决这个问题,这样我们就可以自由地将 ComboBox.SelectedItem 绑定到 ImportColumn
上的 FileColumnHeader
那一行。
<DataTemplate>
<ComboBox
VerticalAlignment="Center"
SelectedItem="{Binding FileColumnHeader}"
SelectionChanged="ComboBox_SelectionChanged"
>
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource listFilterConverter}">
<Binding
Path="DataContext.ListOfWorksheetColumns.UnselectedWorksheetColumns"
RelativeSource="{RelativeSource AncestorType={x:Type ListView}}"
/>
<Binding RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</ComboBox.ItemsSource>
</ComboBox>
</DataTemplate>
我在评论中了解到,SelectionChanged 处理程序正在用于其他可以并且可以说应该在 MVVM 中完成的事情,但它有点复杂。
为了使其正常工作,ImportColumn.FileColumnHeader
需要在其值更改时正确引发 PropertyChanged。由于您 ImportColumn
继承自 BaseViewModel
,我猜您可能为了简洁而省略了该细节。
有点跑题:我相信您的 listFilterConverter
应该将 ComboBox
以外的其他参数作为其第二个参数。无论它从 ComboBox 获得什么属性,您都应该只绑定这些属性。如果消费者需要将其参数包装在 ComboBox
中,则转换器很难重用。但这不是现在的本质。
我有一个包含 2 列的 ListView。第一列是一个简单的字符串。第二个模板设置为单个 ComboBox。行数和 ComboBox 的数量未知。
我的XAML:
<ListView Grid.Row="0" Name="listView" IsSynchronizedWithCurrentItem="True" SelectionMode="Single" Margin="10" ItemsSource="{Binding ImportColumns}">
<ListView.Resources>
<local:ListFilterMultiConverter x:Key="listFilterConverter" />
</ListView.Resources>
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="File column" DisplayMemberBinding="{Binding FileColumnHeader}"/>
<GridViewColumn Header="Worksheet column">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox VerticalAlignment="Center" DataContext="{Binding DataContext,RelativeSource={RelativeSource AncestorType={x:Type ListView}}}" SelectionChanged="ComboBox_SelectionChanged" SelectedIndex="0" >
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource listFilterConverter}">
<Binding Path="ListOfWorksheetColumns.UnselectedWorksheetColumns"/>
<Binding RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</ComboBox.ItemsSource>
</ComboBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
我需要知道第二列的组合框中的内容,以便第一列中的字符串可以与相应组合框的值相关联。问题是我只引用了第一列中的项目。
我的导入列class:
public class ImportColumn : BaseViewModel
{
public string FileColumnHeader { get; set; }
}
BaseViewModel class:
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
}
像您在此处所做的那样绑定 DataContext 是错误的,因为绑定的 DataContext 将是 ComboBox 上任何其他绑定的默认源。这会妨碍您,因为您希望能够绑定到真实数据上下文的属性,即行对象 ImportColumn
。
我们可以通过在多重绑定中使用与 DataContext 相同的 RelativeSource 来解决这个问题,这样我们就可以自由地将 ComboBox.SelectedItem 绑定到 ImportColumn
上的 FileColumnHeader
那一行。
<DataTemplate>
<ComboBox
VerticalAlignment="Center"
SelectedItem="{Binding FileColumnHeader}"
SelectionChanged="ComboBox_SelectionChanged"
>
<ComboBox.ItemsSource>
<MultiBinding Converter="{StaticResource listFilterConverter}">
<Binding
Path="DataContext.ListOfWorksheetColumns.UnselectedWorksheetColumns"
RelativeSource="{RelativeSource AncestorType={x:Type ListView}}"
/>
<Binding RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</ComboBox.ItemsSource>
</ComboBox>
</DataTemplate>
我在评论中了解到,SelectionChanged 处理程序正在用于其他可以并且可以说应该在 MVVM 中完成的事情,但它有点复杂。
为了使其正常工作,ImportColumn.FileColumnHeader
需要在其值更改时正确引发 PropertyChanged。由于您 ImportColumn
继承自 BaseViewModel
,我猜您可能为了简洁而省略了该细节。
有点跑题:我相信您的 listFilterConverter
应该将 ComboBox
以外的其他参数作为其第二个参数。无论它从 ComboBox 获得什么属性,您都应该只绑定这些属性。如果消费者需要将其参数包装在 ComboBox
中,则转换器很难重用。但这不是现在的本质。