Back to Devexpress

WindowedDocumentUIService

wpf-18174-mvvm-framework-services-predefined-set-document-services-windoweddocumentuiservice.md

latest20.1 KB
Original Source

WindowedDocumentUIService

  • Jun 07, 2019
  • 6 minutes to read

The WindowedDocumentUIService is an IDocumentManagerService implementation that allows you to show documents in separate windows.

Getting started with WindowedDocumentUIService

Assume that you need to implement a multi-windowed document UI. When an end-user double-clicks a grid’s row, a new document should be created and shown. This newly created document should display information from the clicked row.

Suppose the GridControl is defined in the following MainView.

xaml
<UserControl x:Class="DXDocumentUIServiceSample.View.MainView"  
    ...
    xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"            
    xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
    xmlns:v="clr-namespace:DXDocumentUIServiceSample.View"
    xmlns:vm="clr-namespace:DXDocumentUIServiceSample.ViewModel" 
    DataContext="{dxmvvm:ViewModelSource Type={x:Type vm:MainViewModel}}">
    <Grid>
        <GroupBox Header="Users">
            <dxg:GridControl Name="grid" ItemsSource="{Binding Users}">
                ...
            </dxg:GridControl>
        </GroupBox>
        ...
    </Grid>
</UserControl>

To handle and process the TableView.RowDoubleClick event at the ViewModel level, subscribe to this event via EventToCommand class as shown in the code snippet below.

xaml
<dxg:GridControl Name="grid" ItemsSource="{Binding Users}">
    ...
    <dxg:GridControl.View>
        <dxg:TableView ... >
            <dxmvvm:Interaction.Behaviors>
                <dxmvvm:EventToCommand 
                    EventName="RowDoubleClick" 
                    Command="{Binding CreateDocumentCommand}" 
                    CommandParameter="{Binding ElementName=grid, Path=CurrentItem}"/>
            </dxmvvm:Interaction.Behaviors>
        </dxg:TableView>
    </dxg:GridControl.View>
</dxg:GridControl>

Then, add the WindowedDocumentUIService to the View’s Interaction.Behaviors collection.

xaml
<v:MainView>
    <dxmvvm:Interaction.Behaviors>
        <dx:WindowedDocumentUIService/>
    </dxmvvm:Interaction.Behaviors>
</v:MainView>

Use the CreateDocument extension method provided by the DocumentManagerServiceExtensions class to create a corresponding document. When the document is created, invoke its IDocument.Show method to show it.

csharp
[POCOViewModel]
public class MainViewModel {
    protected IDocumentManagerService DocumentManagerService { get { return this.GetService<IDocumentManagerService>(); } }
    ...
    public void CreateDocument(object arg) {
        IDocument doc = DocumentManagerService.FindDocument(arg);
        if (doc == null) {
            doc = DocumentManagerService.CreateDocument("DetailedView", arg);
            doc.Id = DocumentManagerService.Documents.Count<IDocument>();
        }
        doc.Show();
    }
}
vb
<POCOViewModel>
Public Class MainViewModel
    Protected ReadOnly Property DocumentManagerService() As IDocumentManagerService
        Get
            Return Me.GetService(Of IDocumentManagerService)()
        End Get
    End Property
    ...
    Public Sub CreateDocument(ByVal arg As Object)
        Dim doc As IDocument = DocumentManagerService.FindDocument(arg)
        If doc Is Nothing Then
            doc = DocumentManagerService.CreateDocument("DetailedView", arg)
            doc.Id = DocumentManagerService.Documents.Count()
        End If
        doc.Show()
    End Sub
End Class

Note that in the code snippet above, we use the FindDocument method to find an already existing document with the specified ViewModel passed via a parameter arg. To get more information about how to create new documents and control existing ones, see the Document Management System topic.

Customization Options

WindowedDocumentUIService provides a set of properties that allow you to customize the document’s view.

These properties are used by the view creation mechanism. You can learn more about them in the following topic: View creation mechanisms

There are also properties that are used to customize the document’s container.

The following code snippet illustrates how to define a custom style for a windowed document’s container (window).

xaml
<dxmvvm:Interaction.Behaviors>
    <dx:WindowedDocumentUIService>
        <dx:WindowedDocumentUIService.WindowStyle>
            <Style TargetType="dx:DXWindow">
                <Setter Property="Width" Value="500"/>
                <Setter Property="Height" Value="300"/>
            </Style>
        </dx:WindowedDocumentUIService.WindowStyle>
    </dx:WindowedDocumentUIService>
</dxmvvm:Interaction.Behaviors>

Example

View Example

xaml
<UserControl x:Class="DXDocumentUIServiceSample.View.DetailedView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:dxc="http://schemas.devexpress.com/winfx/2008/xaml/charts"
    xmlns:common="clr-namespace:DXDocumentUIServiceSample.Common"
    mc:Ignorable="d" 
    d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <GroupBox Header="User Info" Grid.Row="0">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <StackPanel Grid.Column="0">
                    <TextBlock Text="{Binding Path=ID, Converter={common:StringAggregationConverter}, ConverterParameter=ID}"/>
                    <TextBlock Text="{Binding NickName, Converter={common:StringAggregationConverter}, ConverterParameter=Nick}"/>
                </StackPanel>
                <StackPanel Grid.Column="1">
                    <TextBlock Text="{Binding Registration, Converter={common:StringAggregationConverter}, ConverterParameter=Registration}"/>
                    <TextBlock Text="{Binding Rating, Converter={common:StringAggregationConverter}, ConverterParameter=Rating}"/>
                </StackPanel>
            </Grid>
        </GroupBox>
        <GroupBox Header="Activity By User" Grid.Row="1">
            <dxc:ChartControl>
                <dxc:XYDiagram2D>
                    <dxc:SplineAreaSeries2D DisplayName="Global Activity" LabelsVisibility="True" Transparency="0.5" DataSource="{Binding GlobalUserActivity}" ValueDataMember="Count" ArgumentDataMember="Month"/>
                    <dxc:SplineAreaSeries2D DisplayName="Local Activity" LabelsVisibility="True" Transparency="0.5" DataSource="{Binding LocalUserActivity}" ValueDataMember="Count" ArgumentDataMember="Month"/>
                </dxc:XYDiagram2D>
            </dxc:ChartControl>
        </GroupBox>
    </Grid>
</UserControl>
csharp
using DevExpress.Mvvm;
using DXDocumentUIServiceSample.Common;
using System;
using System.Collections.ObjectModel;

namespace DXDocumentUIServiceSample.ViewModel {
    public class UserViewModel : IDocumentContent {
        public virtual int ID { get; set; }
        public virtual string NickName { get; set; }
        public virtual DateTime Registration { get; set; }
        public virtual Decimal Rating { get; set; }
        public virtual ObservableCollection<ActionsPerMonth> GlobalUserActivity { get; set; }
        public virtual ObservableCollection<ActionsPerMonth> LocalUserActivity { get; set; }

        public void Close() {
            DocumentOwner.Close(this, false);
        }

        #region IDocumentContent
        public IDocumentOwner DocumentOwner { get; set; }

        public void OnClose(System.ComponentModel.CancelEventArgs e) { }

        public void OnDestroy() { }

        public object Title {
            get { return String.Format("{1} ({2})",ID, NickName, Registration.ToShortDateString()); }
        }
        #endregion
    }
}
xaml
<dx:DXWindow x:Class="DXDocumentUIServiceSample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" 
    xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
    xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"
    xmlns:dxwui="http://schemas.devexpress.com/winfx/2008/xaml/windowsui" 
    xmlns:dxwuin="http://schemas.devexpress.com/winfx/2008/xaml/windowsui/navigation"    
    xmlns:v="clr-namespace:DXDocumentUIServiceSample.View"
    Title="DocumentUIServices" Height="620" Width="1415" ShowIcon="False">
    <Grid>
        <dx:DXTabControl>
            <dx:DXTabItem Header="WindowedDocumentUIService">
                <v:MainView>
                    <dxmvvm:Interaction.Behaviors>
                        <dx:WindowedDocumentUIService>
                            <dx:WindowedDocumentUIService.WindowStyle>
                                <Style TargetType="dx:DXWindow">
                                    <Setter Property="Width" Value="800"/>
                                    <Setter Property="Height" Value="490"/>
                                    <Setter Property="ShowIcon" Value="False"/>
                                </Style>
                            </dx:WindowedDocumentUIService.WindowStyle>
                        </dx:WindowedDocumentUIService>
                    </dxmvvm:Interaction.Behaviors>
                </v:MainView>
            </dx:DXTabItem>
            <dx:DXTabItem Header="TabbedDocumentUIService">
                <dxdo:DockLayoutManager>
                    <dxdo:LayoutGroup Orientation="Horizontal">
                        <dxdo:LayoutPanel Caption="Users">
                            <v:MainView>
                                <dxmvvm:Interaction.Behaviors>
                                    <dxdo:TabbedDocumentUIService DocumentGroup="{Binding ElementName=documnetGroup}"/>
                                </dxmvvm:Interaction.Behaviors>
                            </v:MainView>
                        </dxdo:LayoutPanel>
                        <dxdo:DocumentGroup x:Name="documnetGroup" Caption="Documents" ItemHeight="*"/>
                    </dxdo:LayoutGroup>
                </dxdo:DockLayoutManager>
            </dx:DXTabItem>
            <dx:DXTabItem Header="DockingDocumentUIService">
                <dxdo:DockLayoutManager>
                    <dxdo:LayoutGroup Orientation="Horizontal">
                        <dxdo:LayoutPanel Caption="Users">
                            <v:MainView>
                                <dxmvvm:Interaction.Behaviors>
                                    <dxdo:DockingDocumentUIService LayoutGroup="{Binding ElementName=layouGroup}"/>
                                </dxmvvm:Interaction.Behaviors>
                            </v:MainView>
                        </dxdo:LayoutPanel>
                        <dxdo:LayoutGroup x:Name="layouGroup" Caption="Panels" ItemHeight="*"/>
                    </dxdo:LayoutGroup>
                </dxdo:DockLayoutManager>
            </dx:DXTabItem>
            <dx:DXTabItem Header="FrameDocumentUIService">
                <dxwui:NavigationFrame AnimationType="SlideHorizontal">
                    <dxwui:NavigationFrame.Source>
                        <v:MainView>
                            <dxmvvm:Interaction.Behaviors>
                                <dxwuin:FrameDocumentUIService/>
                            </dxmvvm:Interaction.Behaviors>
                        </v:MainView>
                    </dxwui:NavigationFrame.Source>
                </dxwui:NavigationFrame>
            </dx:DXTabItem>
        </dx:DXTabControl>        
    </Grid>
</dx:DXWindow>
xaml
<UserControl x:Class="DXDocumentUIServiceSample.View.MainView"  
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" 
    xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"            
    xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
    xmlns:v="clr-namespace:DXDocumentUIServiceSample.View"
    xmlns:vm="clr-namespace:DXDocumentUIServiceSample.ViewModel" 
    mc:Ignorable="d" DataContext="{dxmvvm:ViewModelSource Type={x:Type vm:MainViewModel}}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <GroupBox Header="Users">
            <dxg:GridControl Name="grid" ItemsSource="{Binding Users}">
                <dxg:GridControl.Columns>
                    <dxg:GridColumn FieldName="NickName"/>
                    <dxg:GridColumn FieldName="Registration"/>
                    <dxg:GridColumn FieldName="Rating"/>
                </dxg:GridControl.Columns>
                <dxg:GridControl.View>
                    <dxg:TableView AllowEditing="False" AutoWidth="True" VerticalScrollbarVisibility="Auto" FadeSelectionOnLostFocus="False">
                        <dxmvvm:Interaction.Behaviors>
                            <dxmvvm:EventToCommand EventName="RowDoubleClick" Command="{Binding CreateDocumentCommand}" CommandParameter="{Binding ElementName=grid, Path=CurrentItem}"/>
                        </dxmvvm:Interaction.Behaviors>
                    </dxg:TableView>
                </dxg:GridControl.View>
            </dxg:GridControl>
        </GroupBox>
        <GroupBox Grid.Row="1">
            <StackPanel Orientation="Horizontal">
                <Button Content="Create Document" Command="{Binding CreateDocumentCommand}" CommandParameter="{Binding ElementName=grid, Path=CurrentItem}" Margin="4 2"/>
            </StackPanel>           
        </GroupBox>
    </Grid>
</UserControl>
csharp
using DevExpress.Mvvm;
using DevExpress.Mvvm.POCO;
using DevExpress.Mvvm.DataAnnotations;
using System.Linq;
using System.Collections.ObjectModel;
using DXDocumentUIServiceSample.Common;

namespace DXDocumentUIServiceSample.ViewModel {
    [POCOViewModel]
    public class MainViewModel {
        protected IDocumentManagerService DocumentManagerService { get { return this.GetService<IDocumentManagerService>(); } }
        public virtual ObservableCollection<UserViewModel> Users { get; set; }

        public MainViewModel() {
            Users = DataHelper.GetUsers();   
        }

        public void CreateDocument(object arg) {
            IDocument doc = DocumentManagerService.FindDocument(arg);
            if (doc == null) {
                doc = DocumentManagerService.CreateDocument("DetailedView", arg);
                doc.Id = DocumentManagerService.Documents.Count<IDocument>();
            }
            doc.Show();
        }
    }
}
vb
Imports DevExpress.Mvvm
Imports DevExpress.Mvvm.POCO
Imports DevExpress.Mvvm.DataAnnotations
Imports System.Linq
Imports System.Collections.ObjectModel
Imports DXDocumentUIServiceSample.Common

Namespace DXDocumentUIServiceSample.ViewModel
    <POCOViewModel>
    Public Class MainViewModel
        Protected ReadOnly Property DocumentManagerService() As IDocumentManagerService
            Get
                Return Me.GetService(Of IDocumentManagerService)()
            End Get
        End Property
        Public Overridable Property Users() As ObservableCollection(Of UserViewModel)

        Public Sub New()
            Users = DataHelper.GetUsers()
        End Sub

        Public Sub CreateDocument(ByVal arg As Object)
            Dim doc As IDocument = DocumentManagerService.FindDocument(arg)
            If doc Is Nothing Then
                doc = DocumentManagerService.CreateDocument("DetailedView", arg)
                doc.Id = DocumentManagerService.Documents.Count()
            End If
            doc.Show()
        End Sub
    End Class
End Namespace
vb
Imports DevExpress.Mvvm
Imports DXDocumentUIServiceSample.Common
Imports System
Imports System.Collections.ObjectModel

Namespace DXDocumentUIServiceSample.ViewModel
    Public Class UserViewModel
        Implements IDocumentContent

        Public Overridable Property ID() As Integer
        Public Overridable Property NickName() As String
        Public Overridable Property Registration() As Date
        Public Overridable Property Rating() As Decimal
        Public Overridable Property GlobalUserActivity() As ObservableCollection(Of ActionsPerMonth)
        Public Overridable Property LocalUserActivity() As ObservableCollection(Of ActionsPerMonth)

        Public Sub Close()
            DocumentOwner.Close(Me, False)
        End Sub

        #Region "IDocumentContent"
        Public Property DocumentOwner() As IDocumentOwner Implements IDocumentContent.DocumentOwner

        Public Sub OnClose(ByVal e As System.ComponentModel.CancelEventArgs) Implements IDocumentContent.OnClose
        End Sub

        Public Sub OnDestroy() Implements IDocumentContent.OnDestroy
        End Sub

        Public ReadOnly Property Title() As Object Implements IDocumentContent.Title
            Get
                Return String.Format("{1} ({2})",ID, NickName, Registration.ToShortDateString())
            End Get
        End Property
        #End Region
    End Class
End Namespace