Question

Trying to use DocumentItemSource, DocumentItemStyle and DocumentItemTemplate to display UserControl

Posted 2 years ago by Avatar Ed Starkey

As a summary: Can Docking Windows through MVVM data bind UserControls to DocumentWindows?

I have a project, where my viewmodel contains an ObservableCollection of UserControls and a few strings. When I use the DockingBehavior example as a starting point, I am able to bind the DocumentItemSource to the voewmodel, but the DocumentItemTemplate and DocumentItemStyle fails to render the control, just it's string representation (MVVMDockingTest.TestModel. Also, the additional properties of the DocumentWindow (like Title) are not displayed in the docking tab, though surprisingly they show up in the 'Active Files' dropdown box. 

 

Window XAML

<Window
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:docking="http://schemas.actiprosoftware.com/winfx/xaml/docking" xmlns:local="clr-namespace:MVVMDockingTest" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
		xmlns:sampleCommon="clr-namespace:MVVMDockingTest"
		xmlns:themes="http://schemas.actiprosoftware.com/winfx/xaml/themes" mc:Ignorable="d" x:Class="MVVMDockingTest.MainWindow"
		Title="MainWindow" SizeToContent="WidthAndHeight">
	<Window.Resources>
		<sampleCommon:TestViewModel x:Key="TestViewModelDataSource" d:IsDataSource="True"/>
		
		<Style x:Key="DocumentItemStyle" TargetType="{x:Type docking:DocumentWindow}">
			<Setter Property="Title" Value="{Binding TestName}" />
			<Setter Property="Description" Value="{Binding TestDescription}" />			
		</Style>
		
		<DataTemplate x:Key="DocTemplate" >
			<UserControl Content="{Binding TestName}" BorderThickness="0" BorderBrush="#FFE22B2B" />   
		</DataTemplate>
		
	</Window.Resources>
	<Grid MinHeight="768" MinWidth="1024" DataContext="{Binding Source={StaticResource TestViewModelDataSource}}">
		<docking:DockSite sampleCommon:DockingBehavior.IsManaged="True"  HorizontalAlignment="Stretch" x:Name="dockSite1" VerticalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Margin="0" DocumentItemsSource="{Binding TestCollection}" DocumentItemContainerStyle="{DynamicResource DocumentItemStyle}" DocumentItemTemplate="{StaticResource DocTemplate}">
			<docking:SplitContainer>
				
				<docking:ToolWindowContainer MaxWidth="175" MinWidth="175">
					<docking:ToolWindow Title="Instruments" x:Name="instrumentToolWindow">
						<StackPanel>
							<TextBox MaxWidth="100" MaxHeight="30" MinHeight="30" Margin="30" x:Name="textBox1" />
							<Button MinWidth="75" MinHeight="30" MaxWidth="75" MaxHeight="30" Content="AddTab" Click="Button_Click" x:Name="button1" />
						</StackPanel>    
					</docking:ToolWindow>

					<docking:ToolWindow Title="Test" x:Name="testToolWindow"/>
				</docking:ToolWindowContainer>
				
				<docking:Workspace>
					<docking:TabbedMdiHost>
						<docking:TabbedMdiContainer/>
					</docking:TabbedMdiHost>    
				</docking:Workspace>
				
			</docking:SplitContainer>
		</docking:DockSite>
	</Grid>
</Window>

 

Model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.ComponentModel;

namespace MVVMDockingTest
{
    class TestModel : INotifyPropertyChanged
    {
        private UserControl testControl = new UserControl();
        private string testName;
        private string testDescription;

        public event PropertyChangedEventHandler PropertyChanged;

        public UserControl TestControl
        {
            get
            {
                return testControl;                
            }

            set
            {
                testControl = value;
                OnPropertyChanged("TestControl");
            }
        }

        public string TestName
        {
            get
            {
                return testName;
            }

            set
            {
                testName = value;
                OnPropertyChanged("TestName");
            }
        }

        public string TestDescription
        {
            get
            {
                return testDescription;
            }

            set
            {
                testDescription = value;
                OnPropertyChanged("TestDescription");
            }
        }

        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }

        }

        
    }
}

 

ViewModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Collections;
using ActiproSoftware.Windows.Controls.Docking;

namespace MVVMDockingTest
{
    class TestViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<TestModel> testCollection = new ObservableCollection<TestModel>();
        private string viewModelName;
        public event PropertyChangedEventHandler PropertyChanged;

        

        public ObservableCollection<TestModel> TestCollection
        {
            get
            {
                return testCollection;
            }

            set
            {
                testCollection = value;
                OnPropertyChanged("TestCollection");
            }
        }

        public void addTest(TestModel test)
        {
            testCollection.Add(test);
            OnPropertyChanged("TestCollection");
        }

        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }

        }

        public string ViewModelName
        {
            get
            {
                return viewModelName;
            }

            set
            {
                viewModelName = value;
                OnPropertyChanged("ViewModelName");
            }
        }

        
    }
}

Comments (4)

Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA

Hi Ed,

The DockSite's property mimic the associated ItemsControl properties. This means that your View Model will be put in the Header and Content of the DocumentWindow. The DocumentItemTemplate will be applied to the HeaderTemplate, not the ContentTemplate. So instead you would need to do something like this:

<Style x:Key="DocumentItemStyle" TargetType="{x:Type docking:DocumentWindow}">
	<Setter Property="Title" Value="{Binding TestName}" />
	<Setter Property="Description" Value="{Binding TestDescription}" />			
	<Setter Property="ContentTemplate">
		<Setter.Value>
			<DataTemplate>
				<UserControl Content="{Binding TestControl}" BorderThickness="0" BorderBrush="#FFE22B2B" />   
			</DataTemplate>
		</Setter.Value>
	</Setter>
</Style>

Actipro Software Support
Posted 2 years ago by Ed Starkey

When use your code verbatim, I get the User Control properly, but the title of the created Tab is blank. Shouldn't it derive a title from the name of the contents?

 

Ed

Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA

If you do have a TestName property and it has a non-empty value, then yes, I would think that it would get pulled in via the Setter you have.  Please check your VS output to see if you have any data binding errors listed that might prevent it from working, and ensure that the property has a non-empty value too.


Actipro Software Support
Posted 2 years ago by Ed Starkey

I found the issue,  I had to remove the DocumentItemTemplate binding.

 

Thanks so much.

 

Ed

Information The latest build of this product (2014.1 build 0601) was released 1 month ago, which was after the last post in this thread.

Add a Comment

Please log in to a validated account to post comments.