WPF Caliburn.Micro:在ChildViewModel上绑定DisplayMemberPath

时间:2015-07-14 09:49:43

标签: wpf binding caliburn.micro

我使用VS2013,WPF 4.5,Caliburn Micro 2.0.2。这是我的一个示例项目。 我的ShellViewModel具有基类Conductor,并具有名为Vehicles的model(属性)集合。我还创建了具有基类Screen的ChildViewModel和一个名为ParentVm的属性,该属性包含其父级。在我的真实项目中,我肯定有多个子视图模型(因此,> 1个屏幕)

模型(类Vehicle)包含属性:Manufacturer,Model和Type。

如何在具有ItemsSource =" ParentVm.Vehicles"的ChildView中绑定ListBox的DisplayMemberPath,以便ListBox可以显示类车辆的制造商?

以下是我的示例代码。请随时修改它以显示解决方案。提前谢谢。

public class Vehicle : PropertyChangedBase
{
    public String Manufacturer { get; set; }
    public String Model { get; set; }
    public String Type { get; set; }
}

ShellViewModel

public class ShellViewModel : Conductor<Screen>, IHaveActiveItem
{
    public ChildViewModel ChildVm { get; private set; }
    public ObservableCollection<Vehicle> Vehicles { get; set; }

    public ShellViewModel()
    {
        DisplayName = "Shell Window";
        ChildVm = new ChildViewModel(this);
        Vehicles = new ObservableCollection<Vehicle>();
        SetData();
    }

    public void DisplayChild()
    {
        ActivateItem(ChildVm);
    }

    private void SetData()
    { // fill collection with some sample data
        vh = new Vehicle();
        vh.Manufacturer = "Chevrolet";
        vh.Model = "Spark";
        vh.Type = "LS";
        Vehicles.Add(vh);
    }
}

ShellView

<UserControl x:Class="CMWpfConductorParentChild.Views.ShellView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         d:DesignHeight="300"
         d:DesignWidth="300"
         mc:Ignorable="d">
    <Grid Width="300" Height="300" HorizontalAlignment="Center"
          ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="2*" />
            <RowDefinition Height="10*" />
        </Grid.RowDefinitions>
        <Button x:Name="DisplayChild"
                Grid.Row="0" Width="120" Height="40"
                HorizontalContentAlignment="Center"
                Content="Display Child View" />
        <ContentControl x:Name="ActiveItem" Grid.Row="1" />
    </Grid>
</UserControl>

ChildViewModel

public class ChildViewModel : Screen
{
    public ShellViewModel ParentVm { get; private set; }
    public ChildViewModel(ShellViewModel parent)
    {
        ParentVm = parent;
    }
}

ChildView (以下DisplayMemberPath的绑定无效)

<UserControl x:Class="CMWpfConductorParentChild.Views.ChildView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         d:DesignHeight="300"
         d:DesignWidth="300"
         mc:Ignorable="d">
    <Grid Width="300" Height="300">
        <ListBox DisplayMemberPath="Manufacturer" ItemsSource="ParentVm.Vehicles" />
    </Grid>
</UserControl>

1 个答案:

答案 0 :(得分:1)

您需要添加&#39;绑定&#39; &#39; ItemsSource&#39;的关键字财产:

<ListBox DisplayMemberPath="Manufacturer" ItemsSource="{Binding ParentVm.Vehicles}" />

我修改了您的示例,以展示如何根据约定将属性绑定到子视图。

ShellViewModel

public class ShellViewModel : Screen, IShell
{
    private readonly ChildViewModel _ChildView;
    private readonly IEventAggregator _Aggregator;
    public IList<Vehicle> vehicles = new List<Vehicle>();

    public ShellViewModel(IEventAggregator aggregator, ChildViewModel childView)
    {
        if (aggregator == null)
            throw new ArgumentNullException("aggregator");
        _Aggregator = aggregator;

        if (childView == null)
            throw new ArgumentNullException("childView");
        _ChildView = childView;
        DisplayName = "Shell Window";
    }

    public ChildViewModel ChildView 
    { 
        get { return _ChildView; } 
    }

    public void DisplayChild()
    {
        var vh = new Vehicle() { Manufacturer = "Chevrolet", Model = "Spark", Type = "LS" };
        vehicles.Add(vh);
        _Aggregator.PublishOnUIThreadAsync(new ShowChildViewEvent(vehicles));
    }
}

ShellView

<UserControl x:Class="CaliburnDemo.ShellView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:cal="http://www.caliburnproject.org">
<Grid Width="300" Height="300" HorizontalAlignment="Center"
      ShowGridLines="True">
    <Grid.RowDefinitions>
        <RowDefinition Height="2*" />
        <RowDefinition Height="10*" />
    </Grid.RowDefinitions>
    <Button x:Name="DisplayChild"
            Grid.Row="0" Width="120" Height="40"
            HorizontalContentAlignment="Center"
            Content="Display Child View" />
    <ContentControl cal:View.Model="{Binding ChildView}" Grid.Row="1" />
</Grid>

ChildViewModel

public class ChildViewModel : Screen, IHandle<ShowChildViewEvent>
{
    private BindableCollection<Vehicle> _Vehicles;
    private readonly IEventAggregator _Aggregator;

    public ChildViewModel(IEventAggregator aggregator)
    {
        if (aggregator == null)
            throw new ArgumentNullException("aggregator");
        _Aggregator = aggregator;
        _Aggregator.Subscribe(this);
    }

    public BindableCollection<Vehicle> Vehicles
    {
        get { return _Vehicles; }
        set
        {
            _Vehicles = value;
            NotifyOfPropertyChange(() => Vehicles);
        }
    }

    public void Handle(ShowChildViewEvent message)
    {
        Vehicles = new BindableCollection<Vehicle>(message.Vehicles);
    }
}

ChildView

<UserControl x:Class="CaliburnDemo.ChildView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <ListBox x:Name="Vehicles" DisplayMemberPath="Manufacturer" />
</Grid>

ShowChildViewEvent

public class ShowChildViewEvent
{
    public ShowChildViewEvent(IList<Vehicle> vehicles)
    {
        Vehicles = vehicles;
    }
    public IList<Vehicle> Vehicles { get; private set; }
}

IShell是一个空接口,用于解析容器的根视图。你可以在这里找到更多关于Caliburn的约定: Caliburn Conventions