Добавление ComboBox в ListView в MVVM по статье Джоша Смита - PullRequest
2 голосов
/ 28 июля 2011

Я недавно начал разрабатывать приложения WPF с использованием MVVM.Я следую статье Джоша Смита .Я написал базовый экран, который просто отображает данные в ListView из класса ObservableCollection ViewModel.Это List<string>.Я просто хочу иметь возможность отображать список строк и затем сохранять его обратно в базовом свойстве коллекции Parent.

Должен ли я использовать RelativeSource для связи с ViewModel как DataContext?

Вот код 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>

Спасибо

Пак

1 Ответ

1 голос
/ 29 июля 2011

Я бы просто пошел туда, где DataContext по-прежнему является моделью представления, изменив путь на DataContext.AndOrList и добавив RelativeSource, найдя соответствующий элемент управления.

Далее я бы не стал изменять DataContext ListView, просто поместил все в привязку ItemsSource:

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

Тогда должно сработать следующее и путешествие будет минимальным:

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