按照 Josh Smith 的文章在 MVVM 中的 ListView 中添加 ComboBox

发布于 11-27 00:12 字数 5882 浏览 1 评论 0原文

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

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

这是视图模型代码。

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>

谢谢帕克

I have recently started developing WPF Applications using MVVM. I am following Josh Smith's article. I have written a basic screen which simply displays the data in a ListView from the ViewModel's ObservableCollection class. It's a List<string>. I just simply want to be able to display the List of strings and than be able to save it back in underlying Property of Parent collection.

Should I be using RelativeSource to link with ViewModel as DataContext?

Here's ViewModel Code.

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);
        }
    }
}

Here's the problem Area

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

Here's the whole XAML Code. I am trying to bind the AndOrList collection to 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>

Thanks

Pak

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦亿 2024-12-04 00:12:34

我只需转到 DataContext 仍然是视图模型的位置,将路径更改为 DataContext.AndOrList 并添加一个 RelativeSource 来查找分别控制。

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

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

然后以下操作应该可以工作并且遍历是最少的:

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

I would just go up to where the DataContext is still the view-model, changing the path to DataContext.AndOrList and adding a RelativeSource finding the respective control.

Further i would not change the DataContext of the ListView, just put everything in the ItemsSource binding:

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

Then the following should work and the traveral is minimal:

<ComboBox ItemsSource="{Binding DataContext.AndOrList, RelativeSource={RelativeSource AncestorType=ListView}}">
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文