2015-04-23 78 views
3

我有一个自定义用户控件(ChartControl)我在我的WPF应用程序(MainApp)和内使用我呈现如下:通知视图模型时,查看被渲染/实例化

<ContentControl Grid.Row="1" Content="{Binding ChartControl, Mode=OneWay}" /> 

在启动MainApp执行以下在给定的顺序:

MainApp查看 MainApp视图模型 ChartControl视图模型 ChartControl查看

我从我的MainApp ViewModel的构造函数中实例化了ChartControl ViewModel。问题是,在实例化ChartControl ViewModel之后,我还需要从MainApp内调用ChartControl的方法。

我遇到的问题是我需要ChartControl视图才能将其作为其视图模型的一部分进行调用之前呈现(使其InitializeComponent执行)。

我认为一个解决方案可能是从视图中通知视图模型,当它完全实例化并设置完毕。这是一个可行的解决方案,如果是的话,我会怎么做?

总之,我需要在调用匹配viewmodel的方法之前完全设置视图。我遇到的问题是,在这种情况下,视图模型首先被实例化,然后才呈现视图。

任何想法?

感谢

+0

那是什么方法,为什么需要在执行'InitializeComponent'后调用?你究竟想要做什么?这听起来像一个[xy问题](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)对我来说。 –

+0

它将数据系列呈现为图表表面上的图表,并且遇到图表不显示的问题。我怀疑这是因为视图模型在视图初始化之前构造了图表并且可以呈现它。 –

+0

@SriramSakthivel,正如你正确暗示的那样,这并没有导致我解决我的问题。我的问题是,当我从托管wpf应用程序的视图模型构造函数呈现的系列中时,用户控件中的自定义图表库不呈现图表系列。有关更多详细信息,请参阅http://stackoverflow.com/questions/29805060/wpf-contentcontrol-not-correctly-rendered-when-not-in-view-not-active。 –

回答

5

您可以使用互动的触发射击命令在VM上的任何UI事件

你可以听用户控件的Loaded事件像下面并将其绑定到命令在VM:

<UserControl x:Class="Test.TestView.MyUserControl" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
     x:Name="myControl" > 

<i:Interaction.Triggers> 
    <i:EventTrigger EventName="Loaded"> 
     <i:InvokeCommandAction Command="{Binding ElementName=myControl, Path=OnLoadedCommand}"/> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

而且相信你会在你的虚拟机有命令

public ICommand OnLoadedCommand { get; private set; } 

public MyUserControl() 
{ 
    OnLoadedCommand = new DelegateCommand(OnLoaded); 
} 

public void OnLoaded() 
{ 
} 
+2

如果您的UserControl的DataContext设置为ViewModel(通常),则应该使用Command =“{Path = OnLoadedCommand}”。 myControl(this)不包含OnLoadedCommand(ViewmModel)。在视图(this = myControl =后面的代码)中,您可以直接使用事件(通过事件处理程序)。我已经连接到UserControls的Visibility属性的各种方式的 – honzakuzel1989

5

连接Loaded事件的另一种方法,基本上呈现与nit的答案相同的结果,只需在视图的构造函数中引用viewmodel并添加一个事件处理函数,然后调用您需要调用的任何方法,如下所示:

public MyControl() 
{ 
    InitializeComponent(); 

    this.Loaded += (s, e) => { ((MyViewModel)DataContext).MyInitializer(); }; 
} 

如果您发现语法混淆,您可能需要阅读Anonymous methodsSubscribing to event handlers (using anonymous methods)

+0

,我喜欢这个迄今为止最好的。 – Dave

1

我只使用反射(懒惰耦合解决方案)像Hogler一样使用类似的解决方案。我不想引用特定类型的ViewModel(因为一般性,可交换性等)。

public MyControl() 
{ 
    InitializeComponent(); 
    Loaded += MyControl_Loaded; 
} 

private void MyControl_Loaded(object sender, RoutedEventArgs e) 
{ 
    (DataContext.GetType().GetProperty("LoadedCommand")?. 
    GetValue(DataContext) as ICommand)?. 
    Execute(null); 
} 

ViewModel可以(不必)包含所需的命令,如属性(在这种情况下为LoadedCommand)。而已。

1

在MVVM世界里,我发现当创建一个视觉项目并将其放到视图上(在这种情况下添加到列表中)时,该项目不会在视觉树中,直到加载的事件被触发。

我的视图模型包含XAML视图将显示的可观察集合中的项目列表。

ObservableCollection<MyControl> Items; 

我的项目添加到列表中,但是当我执行需要它是在视觉树并进行可视化树递归的操作,这可能不是后立即发生。相反,我不得不代码是这样的:

var newItem = new MyControl(); 

newItem.Loaded += NewItemLoaded; 

Items.Add(new MyControl()); 

事件处理程序,然后将解开,并执行操作 - 在这一点上根据需要在可视化树:

private void NewItemLoaded(object sender, RoutedEventArgs e) 
{ 
    var item = sender as MyControl; 
    item.Loaded -= NewItemLoaded; 

    // now this item is in the visual tree, go ahead and do stuff ... 
}