【问题标题】:Adding ComboBox in ListView in MVVM following Josh Smith's Article在 Josh Smith 的文章之后,在 MVVM 的 ListView 中添加 ComboBox
【发布时间】:2011-10-15 10:29:52
【问题描述】:

我最近开始使用 MVVM 开发 WPF 应用程序。我关注Josh Smith's article。我编写了一个基本屏幕,它只是在 ViewModel 的 ObservableCollection 类的 ListView 中显示数据。这是List<string>。我只是希望能够显示字符串列表,而不是能够将其保存回父集合的基础属性中。

我应该使用 RelativeSource 作为 DataContext 与 ViewModel 链接吗?

这是 ViewModel 代码。

public class ViewModel
{
    public List<string> AndOrList
    {
        get 
        {
            List<string> andOrList = new List<string> { "AND", "OR" };
            return andOrList;
        }
    }

    public ObservableCollection<BusObjects.Criterion> Criteria
    {
        get
        {
            return new ObservableCollection<BusObjects.Criterion>(_stream.ParseFilterCriteria().Criterias);
        }
    }
}

这里是问题区域

<GridViewColumn Header="And / Or">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox ItemsSource="{Binding AndOrList}">
                                </ComboBox>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>

这是整个 XAML 代码。我正在尝试将 AndOrList 集合绑定到 ComboBox。

<UserControl.Resources>
    <local:FilterCriteriaConverter x:Key="FilterCriteriaConverter"/>

    <CollectionViewSource x:Key="CriteriaList"
                          Source="{Binding Path=Criteria}">
        <CollectionViewSource.SortDescriptions>
            <scm:SortDescription PropertyName="DimName" Direction="Ascending"/>
        </CollectionViewSource.SortDescriptions>
    </CollectionViewSource>

    <Style x:Key="CriteriaItemStyle" TargetType="{x:Type ListViewItem}">
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
        <Style.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="ItemsControl.AlternationIndex" Value="1" />
                    <Condition Property="IsSelected" Value="False" />
                    <Condition Property="IsMouseOver" Value="False" />
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="#EEEEEEEE" />
            </MultiTrigger>
        </Style.Triggers>
    </Style>
</UserControl.Resources>

<DockPanel>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="5"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ListView 
              Name="lstCriteria"
              Grid.Row="0"
              AlternationCount="2" 
              DataContext="{StaticResource CriteriaList}" 
              ItemContainerStyle="{StaticResource CriteriaItemStyle}"
              ItemsSource="{Binding}" DockPanel.Dock="Top">
            <ListView.Resources>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                </Style>
            </ListView.Resources>
            <ListView.View>
                <GridView>
                    <GridViewColumn>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <Rectangle Fill="SteelBlue" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="And / Or">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox ItemsSource="{Binding AndOrList}">
                                </ComboBox>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=DimName}" />
                    <GridViewColumn Header="Oprator" DisplayMemberBinding="{Binding Path=Operator}" />
                    <GridViewColumn Header="Value" DisplayMemberBinding="{Binding Path=DimValue}" />

                </GridView>
            </ListView.View>
        </ListView>
        <Border Grid.Row="1" CornerRadius="4" BorderThickness="1">
            <GridSplitter HorizontalAlignment="Stretch" VerticalAlignment="Center" 
                  Height="3"
                  Background="SteelBlue"/>
        </Border>                
        <Border Name="xmlBorder" Grid.Row="2" VerticalAlignment="Stretch" CornerRadius="4" BorderThickness="1" >
            <StackPanel x:Name="stkPanel" Grid.Row="2" Height="Auto" VerticalAlignment="Stretch" >
                <XMLViewer:Viewer x:Name="xmlViewer" VerticalAlignment="Stretch" />
                <TextBox x:Name="txtXml" TextChanged="XmlTextChanged" Visibility="Hidden"
                         Text="{Binding Path=FilterCriteria, 
                            Converter={StaticResource FilterCriteriaConverter}}" TextWrapping="Wrap"/>
            </StackPanel>
        </Border>
    </Grid>
</DockPanel>

谢谢

【问题讨论】:

  • 语义注释:“Criteria”已经是复数形式:单数形式是“criterion”。因此 - 例如 - ObservableCollection&lt;BusObjects.Criteria&gt; Criterias 应该是 ObservableCollection&lt;BusObjects.Criterion&gt; Criteria...
  • 谢谢,我会在我的代码中解决这个问题。

标签: wpf xaml mvvm combobox viewmodel


【解决方案1】:

我会一直走到 DataContext 仍然是视图模型的位置,将路径更改为 DataContext.AndOrList 并添加 RelativeSource 以查找相应的控件。

此外,我不会更改 ListView 的 DataContext,只需将所有内容都放在 ItemsSource 绑定中:

<ListView ItemsSource="{Binding Source={StaticResource CriteriaList}}" ...>

那么以下应该可以工作并且遍历是最小的:

<ComboBox ItemsSource="{Binding DataContext.AndOrList, RelativeSource={RelativeSource AncestorType=ListView}}">

【讨论】:

  • 嗨 H.B.,感谢您的回复。我从 ListView 开始标记中删除了 DataContext 并根据您的建议替换了它,当我尝试按照您的建议设置 Combobox 的标记时,&lt;ComboBox ItemsSource="{Binding DataContext.AndOrList, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}"/&gt; 但出现以下错误 AncestorType must be specified for RelativeSource in FindAncestor模式。
  • 使用您刚刚发布的确切代码,我没有收到任何错误,因为指定了 AncestorMode。 (顺便说一句,FindAncestor 是多余的,在设置 AncestorType 时,模式是隐式设置的,所以我就省略了)
  • 好的,我只需要重新构建解决方案,错误就消失了。我可以在下拉列表中看到项目。所以我肯定会将此标记为答案。但我仍在努力从组合框中选择的值更新基础属性 (Critarion.AndOr)。
  • 关于如何绑定 ComboBox 有很多问题,在您的情况下,您可能希望将 SelectedItem 绑定到数据对象上的属性之一,即 DataContext,例如SelectedItem="{Binding AndOr}".
  • 是的,做到了。 :) 非常感谢您接受我的新手问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多