2015-04-23 79 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 ... 
}