Notify ViewModel when View is rendered/instantiated

自古美人都是妖i 提交于 2019-12-04 10:31:15

You can make use of Interactivity triggers to fire Command on your VM on any UI event

You can listen to Loaded event of UserControl like below and bind it to Command on your 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>

And sure you will have Command in your VM as

public ICommand OnLoadedCommand { get; private set; }

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

public void OnLoaded()
{
}

Another way to hook up the Loaded event, basically rendering the same result as nit's answer, is simply referencing your viewmodel in the constructor of the view and adding an event handler which in turn calls whatever method you need to call, like this:

public MyControl()
{
   InitializeComponent();

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

If you find the syntax confusing you might want to read up on Anonymous methods and Subscribing to event handlers (using anonymous methods).

I'm using similar solution like Hogler only with reflection (lazy coupled solution). I dont want referencing specific type of my ViewModel (because of generality, interchangeability, etc.).

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 can (dont have to) contain desired command like property (LoadedCommand in this case). Nothing more.

In an MVVM world I found that when creating a visual item and putting it onto the view (in this case adding to a list) the item wouldn't be in the visual tree until the loaded event fired.

My view model contained the items list in an observable collection which the XAML view would display.

ObservableCollection<MyControl> Items;

I'd add an item to the list, but when I perform an operation that requires it to be in the visual tree and performs visual tree recursion, this couldn't happen immediately after. Instead I had to code something like this:

var newItem = new MyControl();

newItem.Loaded += NewItemLoaded;

Items.Add(new MyControl());

The event handler would then unhook and perform the operation - and at this point is was in the visual tree as required:

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 ...
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!