1

I'm working on a WPF/MVVM application that will host a WinForms graphical control for the display of CAD-type geometry.

First, a little background.

Basically, I have a MainWindow with a TreeView on the left and a TabControl on the right. The TreeView simply renders an Observable collection of TreeNode objects. Based on the type of node that's clicked in the tree, the main window's ViewModel creates an instance of an appropriate child ViewModel for the selected tree node (a "workspace"). The new workspace is added to another Observable collection that's bound to the TabControl - which creates a new tab item. This is very similar to the well-known Josh Smith example.

In the XAML of the main window, I'm using <DataTemplate DataType...>

to instantiate an appropriate View for the just created ViewModel.

So far, so good. That all works well. Now, here's where I'm stuck...

One "type" of tree node represents a CAD model. When a node of that type is selected, the view that's instantiated contains the WinForms graphical control (wrapped in a WinFormsHost UserControl). The underlying WinForms control has a "LoadFile()" method that simply requires a filename as input.

The object that's rendered as a tree node in the MainWindow contains the name of the file I need to load. So, I'm trying to figure out the best way to get the filename from the tree node object and pass it to the "LoadFile()" method in the underlying WinForms control.

I have the filename in the MainWindow's ViewModel at the time I create the ViewModel for the CAD control (which, in turn, creates the View containing the WinForms control via the XAML DataTemplate).

Every attempt I've made so far feels like I'm painting myself into a corner. So, am I already too far in the weeds, or does this sound salvageable?

Edited to post code as requested below...

Relevant code-behind of User Control

public string MSIFile
{
    get { return (String)GetValue(MSIFileProperty); }
    set { SetValue(MSIFileProperty, value); }
}

public static readonly DependencyProperty MSIFileProperty =
    DependencyProperty.Register("MSIFIle", typeof(string), typeof(ViewportUserControl),
    new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnMSIFileChanged)));


private static void OnMSIFileChanged(
   DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    Console.WriteLine(e);
}

User Control XAML

<UserControl x:Class="TruNest.UserControls.ViewportUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:vp="clr-namespace:CustomControls;assembly=Winforms"
             d:DesignHeight="300"
             d:DesignWidth="300"
             mc:Ignorable="d" Loaded="UserControl_Loaded">
    <Grid>
        <WindowsFormsHost HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <vp:ViewportCustomUC x:Name="Wrapper" />
        </WindowsFormsHost>
    </Grid>
</UserControl>

Code from MainWindow ViewModel - triggered when new TreeNode is selected

else if (_selectedTreeViewItem is ViewportNode)
{
    ViewportNode node = _selectedTreeViewItem as ViewportNode;
    ViewportViewModel workspace = new ViewportViewModel();
    workspace.TreeNode = _selectedTreeViewItem;
    workspace.Name = String.Format("{0}", node.Name);
    Workspaces.Add(workspace);
    this.SetActiveWorkspace(workspace);
}
Jeff Godfrey
  • 718
  • 8
  • 18
  • Wrap the winforms stuff into a WPF UserControl and create some `DependencyProperties` on that UserControl and have the `DependencyPropertyChangedCallback` pass the `e.NewValue` to the winforms control. – Federico Berasategui Aug 23 '13 at 19:54
  • Thanks for the input HighCore. I'll need to do a little research to determine *how* to accomplish what you're suggesting, but it sounds like a great solution. I've already exposed the necessary dependency property in the WPF wrapper. Now, I just have to figure out how to wire up the PropertyChanged event. I'll be back soon... – Jeff Godfrey Aug 23 '13 at 20:06
  • OK, so I've added a dependency property to the view for storage of the filename and I've wired up the DependencyProperty changed event. So, when the event fires, I should be able to pass the filename on to the Winforms control exactly as needed. However... I don't know how to *set* my new dependency property in the sea of MVVM i'm currently floating in. I'd guess it's really simple, but... – Jeff Godfrey Aug 23 '13 at 20:19
  • Post your current code and XAML. – Federico Berasategui Aug 23 '13 at 20:19
  • Added relevant code to the original post - thanks. – Jeff Godfrey Aug 23 '13 at 20:36
  • So, I've taken HighCore's advice and wired a dependency property in the WPF UserControl wrapper of my underlying WinForms control. When that property is set (with a file name), I should be able to pass it on to the LoadFile() method of the underlying WinForms control. However, I don't know how/when to *set* the new dependency property. I have the value I need to set in the property when I create the ViewModel, but don't understand how/where to set it. – Jeff Godfrey Aug 26 '13 at 15:37
  • I've been able to fill in the missing pieces using the accepted answer here: http://stackoverflow.com/questions/15132538/twoway-bind-views-dependencyproperty-to-viewmodels-property I'm moving forward with this solution, though it seems somewhat painful. If anyone has further thoughts or advice, I'm listening... – Jeff Godfrey Aug 26 '13 at 17:42

0 Answers0