0

我有一个使用视图模型的窗口。此屏幕在一个屏幕上包含 2 个列表视图。第一个列表视图绑定到我的视图模型上名为项目的属性。该属性返回一个模型如下

class ProjectsModel
{
    public string ProjectName { get; set; }
    public ObservableCollection<ProjectModel> ProjectDetails { get; set; }
}

在此类中,ProjectModel 如下所示

public class ProjectModel
{
    public string ProjectName { get; set; }
    public string ProjectId { get; set; }
    public string ProjectFileId { get; set; }
    public string ProjectSource { get; set; }
    public string ClientCode { get; set; }
    public string JobNumber { get; set; }
}

第一个列表视图按我的预期显示项目名称,但我希望这样当我单击任何项​​目时,第二个列表视图应显示其 projectdetails 属性的详细信息。它几乎似乎可以工作,它显示了第一个子项,但我相信它没有被告知第一个列表视图的选定项目已更改。我可以这样做吗?任何想法都将不胜感激,因为我已经把头发拉了几个小时了!

这是xml

<Window x:Class="TranslationProjectBrowser.Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:TranslationProjectBrowser.ViewModels"
    xmlns:local="clr-namespace:TranslationProjectBrowser.Models"
    Title="MainWindow" Height="373" Width="452" Background="LightGray">
<Window.DataContext>
    <vm:ProjectBrowserViewModel></vm:ProjectBrowserViewModel>
</Window.DataContext>
<Window.Resources>
    <ObjectDataProvider x:Key="projectList" ObjectType="{x:Type vm:ProjectBrowserViewModel}" />
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource projectList}}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="176*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="176*" />
        <RowDefinition Height="254*" />
    </Grid.RowDefinitions>
    <DockPanel LastChildFill="True" >
        <TextBlock DockPanel.Dock="Top" Text="Projects" Margin="5,2"></TextBlock>
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
        <TextBox Name="ProjectName" Width="140" Margin="5,2" Height="18" FontFamily="Calibri" FontSize="10"></TextBox>
        <Button Height="18" Width="45" HorizontalAlignment="Left" Margin="0,2" FontSize="10" Content="Add" Command="{Binding Path=AddProject}" CommandParameter="{Binding ElementName=ProjectName, Path=Text}"></Button>
        <TextBlock Text="{Binding Path=ErrorText}" VerticalAlignment="Center" Margin="6,2" Foreground="DarkRed"></TextBlock>
        </StackPanel>
        <ListView Name="project" HorizontalAlignment="Stretch" Margin="2" ItemsSource="{Binding Path=Projects}" IsSynchronizedWithCurrentItem="True">
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding Path=ProjectName}" Header="Name" Width="200" />
                </GridView>
            </ListView.View>
        </ListView>
    </DockPanel>
    <DockPanel LastChildFill="True" Grid.Row="1" >
        <TextBlock DockPanel.Dock="Top" Text="Project Files" Margin="5,2"></TextBlock>
        <ListView  HorizontalAlignment="Stretch" Margin="2" ItemsSource="{Binding Path=Projects/ProjectDetails}" IsSynchronizedWithCurrentItem="True" >
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=ProjectName}"  Width="200" />
                    <GridViewColumn Header="Job Number" DisplayMemberBinding="{Binding Path=JobNumber}" Width="100" />
                </GridView>
            </ListView.View>
        </ListView>
    </DockPanel>
</Grid>

4

2 回答 2

2

您的视图模型应该(至少)实现INotifyPropertyChanged. 这就是 WPF 将如何知道您的选择(或其他属性)何时更改以及需要更新绑定的方式。

所以你应该有这样的东西:

class ProjectsModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String PropertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }
    }

    public string ProjectName 
    { 
        get
        {
            return _projectName;
        }
        set
        {
            _projectName = value;
            NotifyPropertyChanged("ProjectName");
        }       
    }
    public ObservableCollection<ProjectModel> ProjectDetails 
    { 
        get
        {
            return _projectDetails;
        }
        set
        {
            _projectDetails = value;
            NotifyPropertyChanged("ProjectDetails");
        }
    }
}

在 .NET 框架的未来版本中,使用“调用者信息”属性(http://www.thomaslevesque.com/2012/06/13/using-c-5-caller-info-attributes-when -targeting-earlier-versions-of-the-net-framework/)。但截至今天,这通常是如何完成的。

更新

好的,因此根据您的评论,您需要将 ListView 的SelectedItem属性绑定到视图模型上的属性。然后,您也可以将第二个 ListView 绑定到该属性。像这样的东西:

<ListView ... SelectedItem="{Binding Path=FirstListViewSelectedItem, Mode=TwoWay}" .. >

然后你的第二个列表视图将是这样的:

<ListView ... ItemsSource="{Binding Path=FirstListViewSelectedItem.ProjectDetails, Mode=OneWay" .. />
于 2012-06-26T15:03:28.313 回答
2

我在您的代码中看不到任何当前管理。如果您使用 CollectionView,您将免费获得它,请参见以下示例:

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">

    <StackPanel>
        <ListBox ItemsSource="{Binding Path=ProjectsView}" DisplayMemberPath="Name" IsSynchronizedWithCurrentItem="True"/>
        <ListBox ItemsSource="{Binding Path=ProjectsView/ProjectDetails}" />
    </StackPanel>
</Window>

后面的代码:

using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = new VM();
        }
    }

    public class VM
    {
        public VM()
        {
            List<Project> projectsModel = new List<Project>();
            projectsModel.Add(new Project("AAA"));
            projectsModel.Add(new Project("BBB"));
            projectsModel.Add(new Project("CCC"));

            ProjectsView = CollectionViewSource.GetDefaultView(projectsModel);
        }

        public ICollectionView ProjectsView { get; private set; }
    }

    public class Project
    {
        public Project(string name)
        {
            Name = name;
        }

        public string Name { get; private set; }
        public IEnumerable<string> ProjectDetails
        {
            get
            {
                for (int i = 0; i < 3; i++)
                {
                    yield return string.Format("{0}{1}", Name, i);
                }
            }
        }
    }
}
于 2012-06-26T16:19:03.670 回答