Caliburn.Micro得到它在的MainView他们的ViewModels用户控件绑定 [英] Caliburn.Micro getting it to bind UserControls in a MainView to their ViewModels

查看:1395
本文介绍了Caliburn.Micro得到它在的MainView他们的ViewModels用户控件绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我想尝试劈开什么了大量的控件我有我的主要形式为用户控件。



现在我把用户控件的浏览文件夹内的沿的MainView并命名它们,LeftSideControlView.xaml和RightSideControlView.xaml。相应的ViewModels都在的ViewModels文件夹中称为LeftSideControlViewModel等



我成功添加用户控件到MAINVIEW:

 <网格和GT; 
< Grid.ColumnDefinitions>
< ColumnDefinition />
< ColumnDefinition />
< /Grid.ColumnDefinitions>
<用户控件:LeftSideControlView CAL:Bind.Model ={结合}/>
<用户控件:RightSideControlView CAL:Bind.Model ={结合}
Grid.Column =1/>
< /网格和GT;



他们正确地显示在设计师。下面是他们中的一个在XAML:

 <用户控件X:类=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:可忽略=D
D:DesignHeight =300D:DesignWidth =300>
<网格和GT;
<&StackPanel的GT;
<标号x:名称=TEXT字号=25的Horizo​​ntalAlignment =中心保证金=10/>
<文本框X:NAME =TextBox1的
WIDTH =200
的Horizo​​ntalAlignment =中心字号=25保证金=10/>
<按钮WIDTH =200HEIGHT =50CONTENT =按钮!保证金=20/>
< / StackPanel的>
< /网格和GT;





我增加了的ViewModels和该AppBootstrapper内部接口使用Castle.Windsor卡利

 公共类ApplicationContainer:WindsorContainer 
{
公ApplicationContainer()
{
//这里$ b $注册的所有依赖b寄存器(
Component.For< IWindowManager方式>()ImplementedBy<窗口管理方式>()LifeStyle.Is(LifestyleType。辛格尔顿),
Component.For< IEventAggregator>()ImplementedBy< EventAggregator>()LifeStyle.Is(LifestyleType.Singleton),
Component.For< ILeftSideControlViewModel>()ImplementedBy< LeftSideControlViewModel>( ),
Component.For< IRightSideControlViewModel>()ImplementedBy< RightSideControlViewModel>()
);

RegisterViewModels();
}

私人无效RegisterViewModels()
{
寄存器(AllTypes.FromAssembly(的GetType()大会)
。凡(X => x.Name.EndsWith(视图模型))
.Configure(X => x.LifeStyle.Is(LifestyleType.Transient)));
}



这里的LeftSideControlViewModel类:

 使用屏幕= Caliburn.Micro.Screen; 

命名空间TwitterCaliburnWPF.Library.ViewModels
{
公共类LeftSideControlViewModel:屏幕,ILeftSideControlViewModel
{
私人字符串_text =你好从左侧!
私人字符串_textBox1 =输入文字在这里;

公共字符串文本
{
{返回_text; }
}

公共字符串TextBox1的
{
{返回_textBox1; }
}
}
}



这里的MainViewModel和我要去了我在Caliburn.Micro机制的文档阅读,因为之前我想这没有在MainViewModel告诉它加载这些2控制或显示这两个控件是特别。



不过,当应用程序启动并运行的数值并不具有约束力,从各自的ViewModels的用户控件。

 命名空间TwitterCaliburnWPF.Library.ViewModels 
{
公共类MainViewModel:导体与LT; IScreen>
{
公共MainViewModel()
{
ShowLeftControl();
ShowRightControl();
}

私人无效ShowRightControl()
{
ActivateItem(新RightSideControlViewModel());
}

私人无效ShowLeftControl()
{
ActivateItem(新LeftSideControlViewModel());
}

公共字符串TextToDisplay
{
{返回从视图模型来了! }
}
}
}


解决方案

您不需要使用指挥在这里。这基本上是用于导航场景。刚上提出两个公共属性的 MainViewModel 一个 RightSideControlViewModel 称为RightSide,一个用于 LeftSideControlViewModel ,堪称LeftSide。然后,而不是直接在你的MainView实例的用户控件,创建两个 ContentControls ,一个具有 X:NAME =LeftSide和其他与 X:NAME =RightSide这是实现它的视图模型,第一种方式。如果你想这样做视图一,保持用户控制定义在你的MainView,但改变Bind.Model,使其指向您所创建,如 Bind.Model =新的属性{结合LeftSide}



基本上,你有事情的方式定义....绑定只是没有在正确的对象指向,更或更少。你已经得到了指挥在那里,你不需要做到这一点。你可能想保留它,如果你打算有某种导航架构。请记住,当你调用ActivateItem在导体上,你基本上改变其ActiveItem财产;只有一个模型在同一时间被激活。在上述情况下激活两个项目,但是只有第二个保持有效。此外,在你看来,没有什么是必然ActiveItem。



我希望这是有道理的!


I have a MainView.xaml, binding to a MainViewModel just fine.

What I wanted to try out was splitting a lot of controls I have on my main form into UserControls.

Now I put the UserControls inside the Views folder along with the MainView and named them, LeftSideControlView.xaml and RightSideControlView.xaml. The corresponding ViewModels are in the ViewModels folder called LeftSideControlViewModel, etc.

I successfully added the usercontrols to the mainview:

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

they show up correctly in the designer. Here's one of them in 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>

I added the viewmodels and their interfaces inside the AppBootstrapper for Caliburn using Castle.Windsor.

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

Here's the LeftSideControlViewModel class:

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

Here's the MainViewModel and I'm going off what I read in the Caliburn.Micro documention, as before I tried this nothing was specifically in the MainViewModel to tell it to load these 2 controls or show these 2 controls.

Still when the app is up and running the values are not binding to the usercontrols from their respective viewmodels.

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!"; }
      }
   }
}

解决方案

You don't need to use a Conductor here. That's basically used for navigation scenarios. Just make two public properties on your MainViewModel one for RightSideControlViewModel called RightSide and one for LeftSideControlViewModel, called LeftSide. Then, instead of instantiating your UserControls directly in your MainView, create two ContentControls, one with x:Name="LeftSide" and the other with x:name="RightSide" This is a view-model-first way of accomplishing it. If you want to do it view-first, keep the user control definitions in your MainView, but change the Bind.Model so that it points to the new properties you created, like Bind.Model="{Binding LeftSide}"

Basically, the way you have things defines....the bindings just aren't pointing at the right objects, more or less. You've got the Conductor in there, which you don't need to accomplish this. You may want to keep it if you intend to have some sort of navigation architecture. Remember that when you call ActivateItem on a Conductor, you are basically changing its ActiveItem property; only one model with be active at a time. In the case above you activate both items, but only the second one remains active. Furthermore, in your view, nothing is bound to ActiveItem.

I hope this makes sense!

这篇关于Caliburn.Micro得到它在的MainView他们的ViewModels用户控件绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆