Модель WPF и MDI - PullRequest
       12

Модель WPF и MDI

1 голос
/ 21 ноября 2011

После многих лет разработки Windows Forms я решил поэкспериментировать с WPF.В компании, в которой я работаю, я создал большое количество программного обеспечения на основе стиля MDI, и я хотел бы продолжать делать это при использовании WPF.

Я знаю, что MDI не «поддерживается» моим WPFи я пытаюсь найти работу вокруг этого вопроса.Я также знаю, что могу имитировать поведение MDI с помощью элемента управления вкладками WPF, но для меня это не оптимальное решение.

Пользователи здесь используют программное обеспечение с формой MDI и многими формами, которые служат для мониторинга.различные задачи, асинхронно и всегда видимые.

Можно ли как-нибудь реализовать эту функцию в WPF без вкладки или с помощью сторонних элементов управления и без некоторого взаимодействия WinForms?

Ответы [ 2 ]

0 голосов
/ 21 ноября 2011

Я построил MDI для WPF с использованием функции управления всплывающими окнами.Я предлагаю вам не использовать общий способ выигрышных форм, основанный на отдельных элементах управления, а использовать MVVM для WPF.Итак, каждое окно MDI - это Popup, которое оборачивает модель представления.Само приложение является базовым окном, в котором размещаются модели представлений и работает с окнами через модели представлений.

Я представляю пример окна MDI из реальной жизни.Имейте в виду, что это не полный образец, но достаточно продемонстрировать некоторые основные концепции.Все необходимые классы являются пользовательскими, поэтому не зависят от компонентов третьей части:

<DataTemplate DataType="{x:Type vm:Pane}">
    <DataTemplate.Resources>
        <ControlTemplate x:Key="uiFreePaneTemplate" TargetType="ContentControl">
            <Popup  
                x:Name="PART_DRAG" HorizontalOffset="{Binding X}" VerticalOffset="{Binding Y}"
                IsOpen="{Binding IsOpened}" VerticalAlignment="Top" HorizontalAlignment="Left"
                AllowsTransparency="True">
                <Border 
                    Width="{Binding Width}" Height="{Binding Height}" 
                    BorderThickness="2,2,2,2" Margin="0" CornerRadius="5" 
                    BorderBrush="{StaticResource WindowBackgroundBrush}"
                    Background="{StaticResource WindowBackgroundBrush}">
                    <ContentControl Template="{StaticResource Resizer}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>

                            <!--Pane header-->
                            <Thumb  Grid.Row="0" Width="Auto" Height="21">
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="DragDelta">
                                        <mvvm:EventToCommand Command="{Binding DragCommand}" PassEventArgsToCommand="True" />
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                                <Thumb.Template>
                                    <ControlTemplate>
                                        <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                                            <Grid.Background>
                                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                    <GradientStop Color="#FF0C286C" Offset="1"/>
                                                    <GradientStop Color="Transparent"/>
                                                </LinearGradientBrush>
                                            </Grid.Background>

                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="*"/>
                                                <ColumnDefinition Width="Auto"/>
                                            </Grid.ColumnDefinitions>

                                            <Label Content="{Binding Name}" Grid.Column="0" />

                                            <Button Template="{StaticResource CloseButton}" 
                                                Grid.Column="1"
                                                Margin="1,1,3,1" />
                                        </Grid>
                                    </ControlTemplate>
                                </Thumb.Template>
                            </Thumb>

                            <Grid Grid.Row="1" Background="{StaticResource ControlBackgroundBrush}">
                                <!--Pane content-->
                                <AdornerDecorator>
                                    <ContentPresenter Content="{TemplateBinding Content}" />
                                </AdornerDecorator>

                                <ResizeGrip x:Name="WindowResizeGrip" 
                                    HorizontalAlignment="Right" 
                                    VerticalAlignment="Bottom"
                                    IsTabStop="false"/>
                            </Grid>
                        </Grid>
                    </ContentControl>
                </Border>
            </Popup>
        </ControlTemplate>

    </DataTemplate.Resources>

    <ContentControl x:Name="uiBorder" Content="{Binding Model}" />

    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding IsFree}" Value="True">
            <Setter TargetName="uiBorder" Property="ContentControl.Template" Value="{StaticResource uiFreePaneTemplate}" />
        </DataTrigger>
    </DataTemplate.Triggers>        
</DataTemplate>

Просмотр модели:

public class Pane : HideableChildViewModel, IPane
{
    private IViewModel _model;
    private bool _isFree = true;
    private string _name;
    private double _coordinateX;
    private double _coordinateY;
    private double _width = 200.0;
    private double _height = 400.0;

    private ICommand _closeCommand;
    private ICommand _dragCommand;
    private ICommand _resizeCommand;

    /// <summary>
    /// Initializes a new instance of the Pane class.
    /// </summary>
    /// <param name="parent">The parent view model</param>
    /// <param name="parentPropertySelector">Selector of the parent property</param>
    /// <param name="model">VM to place within the pane</param>
    public Pane(
        IViewModel parent, 
        Expression<Func<object>> parentPropertySelector,
        IViewModel model)
        : base(parent, parentPropertySelector)
    {
        this.Model = model;

        this._dragCommand = new DragPaneCommand();
        this._resizeCommand = new ResizeCommand();
        if (model != null && model is ICloseableVM)
        {
            this._closeCommand = new ClosePaneCommand();
        }
        else
        {
            this._closeCommand = new HideCommand();
        }
    }

    #region Properties

    /// <summary>
    /// Gets or sets VM to place within the pane
    /// </summary>
    public IViewModel Model
    {
        get 
        {
            return this._model; 
        }

        set 
        {
            if (this._model != value)
            {
                this._model = value;
                this.RaisePropertyChanged(() => this.Model);
            }
        }
    }

    /// <summary>
    /// Gets or sets name of the pane
    /// </summary>
    [LayoutSettings(IsKey = true)]
    public string Name
    {
        get 
        {
            return this._name; 
        }

        set 
        {
            if (this._name != value)
            {
                this._name = value;
                this.RaisePropertyChanged(() => this.Name);
            }
        }
    }

    /// <summary>
    /// Gets or sets X coordinate
    /// </summary>
    [LayoutSettings]
    public double X
    {
        get 
        {
            return this._coordinateX; 
        }

        set 
        {
            if (this._coordinateX != value)
            {
                this._coordinateX = value;
                this.RaisePropertyChanged(() => this.X);
            }
        }
    }

    /// <summary>
    /// Gets or sets Y coordinate
    /// </summary>
    [LayoutSettings]
    public double Y
    {
        get 
        {
            return this._coordinateY; 
        }

        set 
        {
            if (this._coordinateY != value)
            {
                this._coordinateY = value;
                this.RaisePropertyChanged(() => this.Y);
            }
        }
    }

    /// <summary>
    /// Gets or sets width
    /// </summary>
    [LayoutSettings]
    public double Width
    {
        get
        {
            return this._width;
        }

        set
        {
            if (this._width != value)
            {
                this._width = value;
                this.RaisePropertyChanged(() => this.Width);
            }
        }
    }

    /// <summary>
    /// Gets or sets height
    /// </summary>
    [LayoutSettings]
    public double Height
    {
        get
        {
            return this._height;
        }

        set
        {
            if (this._height != value)
            {
                this._height = value;
                this.RaisePropertyChanged(() => this.Height);
            }
        }
    }

    /// <summary>
    /// Gets or sets a value indicating whether pane is free
    /// </summary>
    public bool IsFree
    {
        get
        {
            return this._isFree;
        }

        set
        {
            if (this._isFree != value)
            {
                this._isFree = value;
                this.OnIsFreeChanged(this._isFree);
                this.RaisePropertyChanged(() => this.IsFree);
            }
        }
    }

    #endregion

    #region Commands

    /// <summary>
    /// Gets command for pane closing
    /// </summary>
    public ICommand CloseCommand
    {
        get { return this._closeCommand; }
    }

    /// <summary>
    /// Gets command for pane dragging
    /// </summary>
    public ICommand DragCommand
    {
        get { return this._dragCommand; }
    }

    /// <summary>
    /// Gets command for pane resize
    /// </summary>
    public ICommand ResizeCommand
    {
        get { return this._resizeCommand; }
    }

    #endregion

    private void OnIsFreeChanged(bool isFree)
    {
        if (!isFree)
        {
            return;
        }

        IDockContainer oContainer = ((IChildViewModel)((IChildViewModel)this.Parent).Parent).Parent as IDockContainer;
        if (oContainer != null)
        {
            this.SetParent(oContainer, () => oContainer.FreeItems);
        }
    }
}
0 голосов
/ 21 ноября 2011

Один из вариантов - использовать следующий проект: http://wpfmdi.codeplex.com/

Другой вариант - сделать что-то самостоятельно, что позволяет делать интересные вещи, связанные с поведением нескольких мониторов и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...