【问题标题】:Caliburn.Micro getting it to bind UserControls in a MainView to their ViewModelsCaliburn.Micro 让它将 MainView 中的 UserControls 绑定到他们的 ViewModels
【发布时间】:2012-04-17 08:11:00
【问题描述】:

我有一个 MainView.xaml,绑定到 MainViewModel 就好了。

我想尝试的是将主窗体上的许多控件拆分为 UserControls。

现在我将 UserControls 与 MainView 一起放在 Views 文件夹中,并将它们命名为 LeftSideControlView.xaml 和 RightSideControlView.xaml。对应的 ViewModel 位于名为 LeftSideControlViewModel 等的 ViewModels 文件夹中。

我成功地将用户控件添加到主视图:

 <Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <UserControls:LeftSideControlView cal:Bind.Model="{Binding}" />
    <UserControls:RightSideControlView cal:Bind.Model="{Binding}"
                                  Grid.Column="1" />
</Grid>

它们在设计器中正确显示。这是 xaml 中的其中一个:

 <UserControl x:Class="TwitterCaliburnWPF.Library.Views.LeftSideControlView"
         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>
    <StackPanel>
        <Label x:Name="Text" FontSize="25" HorizontalAlignment="Center" Margin="5"/>
        <TextBox x:Name="TextBox1"
                 Width="200"
                 HorizontalAlignment="Center" FontSize="25" Margin="5" />
        <Button Width="200" Height="50" Content="Button!" Margin="20" />
    </StackPanel>
</Grid>

我使用 Castle.Windsor 在 AppBootstrapper for Caliburn 添加了视图模型及其接口。

 public class ApplicationContainer : WindsorContainer
 {
  public ApplicationContainer()
  {
     // Register all dependencies here
     Register(
        Component.For<IWindowManager>().ImplementedBy<WindowManager>().LifeStyle.Is(LifestyleType.Singleton),
        Component.For<IEventAggregator>().ImplementedBy<EventAggregator>().LifeStyle.Is(LifestyleType.Singleton),
        Component.For<ILeftSideControlViewModel>().ImplementedBy<LeftSideControlViewModel>(),
        Component.For<IRightSideControlViewModel>().ImplementedBy<RightSideControlViewModel>()
        );

     RegisterViewModels();
  }

  private void RegisterViewModels()
  {
     Register(AllTypes.FromAssembly(GetType().Assembly)
                  .Where(x => x.Name.EndsWith("ViewModel"))
                  .Configure(x => x.LifeStyle.Is(LifestyleType.Transient)));
  }

这是 LeftSideControlViewModel 类:

 using Screen = Caliburn.Micro.Screen;

 namespace TwitterCaliburnWPF.Library.ViewModels
 {
    public class LeftSideControlViewModel : Screen, ILeftSideControlViewModel
    {
       private string _text = "Hello from the Left side!";
       private string _textBox1 = "Enter Text Here";

       public string Text
       {
          get { return _text; }
       }

       public string TextBox1
       {
          get { return _textBox1; }
       }
    }
 }

这里是 MainViewModel,我将关闭我在 Caliburn.Micro 文档中读到的内容,因为在我尝试之前,MainViewModel 中没有专门告诉它加载这两个控件或显示这两个控件。

当应用启动并运行时,这些值并未绑定到各自视图模型中的用户控件。

namespace TwitterCaliburnWPF.Library.ViewModels
{
   public class MainViewModel : Conductor<IScreen>
   {
      public MainViewModel()
      {
         ShowLeftControl();
         ShowRightControl();
      }

      private void ShowRightControl()
      {
         ActivateItem(new RightSideControlViewModel());
      }

      private void ShowLeftControl()
      {
         ActivateItem(new LeftSideControlViewModel());
      }

      public string TextToDisplay
      {
         get { return "Coming from the ViewModel!"; }
      }
   }
}

【问题讨论】:

    标签: c# wpf caliburn.micro


    【解决方案1】:

    您无需在此处使用Conductor。这基本上用于导航场景。只需在您的MainViewModel 上创建两个公共属性,一个用于RightSideControlViewModel,称为 RightSide,另一个用于LeftSideControlViewModel,称为 LeftSide。然后,不要直接在 MainView 中实例化 UserControl,而是创建两个 ContentControls,一个使用 x:Name="LeftSide",另一个使用 x:name="RightSide"。这是一种视图模型优先的实现方式。如果您想先查看,请将用户控件定义保留在 MainView 中,但更改 Bind.Model 使其指向您创建的新属性,例如 Bind.Model="{Binding LeftSide}"

    基本上,您拥有事物的方式定义了......绑定只是没有指向正确的对象,或多或少。你有指挥者在那里,你不需要完成这个。如果您打算拥有某种导航架构,您可能希望保留它。请记住,当您在 Conductor 上调用 ActivateItem 时,您基本上是在更改其 ActiveItem 属性;一次只有一个模型处于活动状态。在上述情况下,您激活了这两个项目,但只有第二个仍然处于活动状态。此外,在您看来,没有任何东西与 ActiveItem 绑定。

    我希望这是有道理的!

    【讨论】:

      猜你喜欢
      • 2020-12-29
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      • 2015-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-01
      相关资源
      最近更新 更多