1
votes

In my MainWindow VM i open the Views from my UserControls like this. Usercontrol1 is the name of the View made in Xaml. In my ViewModel of my MainWindow:

   private static Grid _myMainGrid;

    public static Grid MyMainGrid
    {
        get { return _myMainGrid; }
        set { _myMainGrid = value; }
    }

    private void OpenUserControl(UserControl myUS)
    {
        if (MyMainGrid.Children.Count > 0)
        {
            MyMainGrid.Children.RemoveAt(0);
        }
        Grid.SetColumn(myUS, 1);
        Grid.SetRow(myUS, 0);
        MyMainGrid.Children.Add(myUS);
    }
    private void FindGrid(object obj)
    {
        var myGrd = obj as Grid;
        if (myGrd != null)
        {
            MyMainGrid = myGrd;
        }
    }

The command binding to the Button executes this.

private void ExecuteCMD_OpenUserControl1(object obj)
    {
        FindGrid(obj);
        Usercontrol1 _ucItem = new Usercontrol1();
        OpenUserControl(_ucItem);
    }

Now i want to open Usercontrol2 replacing Usercontrol1 in MyMainGrid from my MainWindow by pressing a button in Usercontrol1. So i have to access the parent Window.

Tried using this methode but can't get it to work in my case.

2
You don't want or need a usercontrol to do anything with its parent. Not a good idea. What's the real goal here? You should in any case be using MVVM/XAML, not creating controls in codebehind.15ee8f99-57ff-4f92-890c-b56153
I already made the usercontrols in MVVM/Xaml. I have a datagrid in UsercontrolOrderOversight and i want to open that specific order in his UsercontrolOrder but i want it to open it and replace the oversightJurgen Volders
So do they have viewmodels? I don't know what "open it and replace the oversight" means. You should do your entire application with MVVM, not just a few small corners while the rest tries to be winforms.15ee8f99-57ff-4f92-890c-b56153
Yes they have. When i open a usercontrol i mean open the Xaml View it is binded with datacontext to it's viewmodelJurgen Volders
Does your main window have a viewmodel?15ee8f99-57ff-4f92-890c-b56153

2 Answers

1
votes

Let's say you have two children; it's trivial to generalize this to any number of children. Fortunately you've already got viewmodels and views, so we're most of the way there. It's just a matter of wiring it all together in a way that works well with WPF.

Here's a set of skeletal viewmodels. Main, and two children. MainViewModel creates its two child instances. ChildOneViewModel has a Next button command, bound to a Button in ChildOneView.xaml.

When the user clicks that button, we want to switch the active view to child two. Rather than have dependencies going in all directions, ChildOneViewModel is ignorant of what "next" really means; its parent, MainViewModel, is in charge of that. Everybody knows about his children; you've found that in programming, making a class know about its siblings or its parent creates problems.

So all ChildOneViewModel does is expose an event so MainViewModel knows when the button is clicked, and can take any action it likes when that happens. This is cool because what if we could be going to one of two different "next" pages, depending on what the user did in ChildOne? If we move that responsibility to the parent, everything becomes simpler. Easier to write, easier to reuse in a different context.

#region MainViewModel Class
public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {
        ChildOne = new ChildOneViewModel();
        ChildTwo = new ChildTwoViewModel();

        ActiveChild = ChildOne;

        ChildOne.NextButtonClicked += (s, e) => ActiveChild = ChildTwo;
    }

    #region ActiveChild Property
    private INotifyPropertyChanged _activeChild = default(INotifyPropertyChanged);
    public INotifyPropertyChanged ActiveChild
    {
        get { return _activeChild; }
        set
        {
            if (value != _activeChild)
            {
                _activeChild = value;
                OnPropertyChanged();
            }
        }
    }
    #endregion ActiveChild Property

    public ChildOneViewModel ChildOne { get; private set; }
    public ChildTwoViewModel ChildTwo { get; private set; }
}
#endregion MainViewModel Class

#region ChildOneViewModel Class
public class ChildOneViewModel : ViewModelBase
{
    public event EventHandler NextButtonClicked;

    //  You already know how to implement a command, so I'll skip that. 
    protected void NextButtonCommandMethod()
    {
        NextButtonClicked?.Invoke(this, EventArgs.Empty);
    }
}
#endregion ChildOneViewModel Class

#region ChildTwoViewModel Class
public class ChildTwoViewModel : ViewModelBase
{
}
#endregion ChildTwoViewModel Class

And here's the XAML that translates all of that into actual UI at runtime:

<Window.Resources>
    <!-- 
    These are "implicit datatemplates": They have no x:Key, so they'll be 
    automatically used to display any content of the specified types. 
    -->
    <DataTemplate DataType="{x:Type local:ChildOneViewModel}">
        <local:ChildOneView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:ChildTwoViewModel}">
        <local:ChildTwoView />
    </DataTemplate>
</Window.Resources>
<Grid>

    <!-- other stuff -->
    <UserControl
        Content="{Binding ActiveChild}"
        />
    <!-- other stuff -->

You don't need OpenUserControl(), FindGrid(), any of that stuff.

-1
votes

I don't fully understand the structure of your application and there are most probably better ways of doing whatever you are trying to do, but you could get a reference to any open window in your application using the Application.Current.Windows property if that's your main issue:

var mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();

Inside a loaded UserControl, you should also be able to get a reference to the parent window of this UserControl like this:

var mainWindow = Window.GetWindow(this) as MainWindow;