Вставить панель формы Windows в элемент управления WPF - PullRequest
0 голосов
/ 07 декабря 2018

Я пытаюсь создать модные элементы управления WPF для настольных приложений Windows.Мне интересно, возможно ли выставить встроенную панель в элемент управления WPF.Идея состоит в том, чтобы создать панель с названием ленты.Кнопка будет использоваться для развертывания или скрытия элементов управления.

Вот моя новая панель:

<UserControl x:Class="TestRibbonPanel.RibbonPanel.XamlRibbonPanel"
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:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" 
xmlns:local="clr-namespace:TestRibbonPanel.RibbonPanel"
mc:Ignorable="d" 
d:DesignHeight="150" d:DesignWidth="200" MinHeight="40" x:Name="uc">
<UserControl.Resources>
    <local:BorderHeightConverter x:Key="BhConverter"/>
</UserControl.Resources>
<Grid Background="Transparent">
    <Grid x:Name="grd" Height="20" VerticalAlignment="Top">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
        </Grid.RowDefinitions>
        <Button Grid.Column="0" Grid.Row="0" x:Name="btn" Background="#333333" Click="Btn_Click"/>
        <TextBlock Grid.Column="1" Grid.Row="0" Text="Title" Background="#333333" Foreground="#CCCCCC"/>
    </Grid>
    <Popup x:Name="pu" StaysOpen="True" PlacementTarget="{Binding ElementName=grd}" AllowsTransparency="True" PopupAnimation="Slide" IsOpen="True">
        <Border x:Name="brd" Background="White" CornerRadius="0,0,10,10" BorderThickness="2" BorderBrush="Black" Height="{Binding Path=ActualHeight, ElementName=uc, Converter={StaticResource BhConverter}, FallbackValue=130}" Width="{Binding ActualWidth, ElementName=grd, FallbackValue=200}" SizeChanged="Brd_SizeChanged">
            <WindowsFormsHost>
                <wf:Panel x:Name="pnl" BorderStyle="FixedSingle" BackColor="Red"/>
            </WindowsFormsHost>
        </Border>
    </Popup>
</Grid>

В приведенном ниже коде я использовал Систему.Windows.Controls.Panel как свойство с именем ContentPanel:

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace TestRibbonPanel.RibbonPanel
{
/// <summary>
/// Logique d'interaction pour XamlRibbonPanel.xaml
/// </summary>
public partial class XamlRibbonPanel : UserControl
{
    public static readonly DependencyProperty IsOPenProperty = DependencyProperty.Register("IsOpen", typeof(bool), typeof(XamlRibbonPanel), new PropertyMetadata(true));
    public bool IsOPen
    {
        get { return (bool)GetValue(IsOPenProperty); }
        set
        {
            SetValue(IsOPenProperty, value);
        }
    }
    public System.Windows.Forms.Panel ContentPanel
    {
        get { return pnl; }
    }

    public XamlRibbonPanel()
    {
        InitializeComponent();
    }
    private void Brd_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        pnl.Size = new System.Drawing.Size((int)brd.ActualWidth, (int)brd.ActualHeight);
    }

    private void Btn_Click(object sender, RoutedEventArgs e)
    {
        pu.IsOpen = !pu.IsOpen;
    }
}

public class BorderHeightConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (double)value - 20;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
    }
}

Теперь я поместил этот элемент управления WPF в оболочку формы Windows, используя класс интеграции ElementHost с именем EH, внедряющий элемент управления XamlRibbonPanel .:

    [DesignerAttribute(typeof(XRibbonPanelDesigner))]
public class XRibbonPanel : UserControl
{
    private System.ComponentModel.IContainer _components = null;
    private System.Windows.Forms.Integration.ElementHost EH;
    private RibbonPanel.XamlRibbonPanel _xp = null;
    private Panel _contentPanel = null;

    public Panel ContentPanel
    {
        get { return _contentPanel; }
    }

    /// <summary>
    /// .ctor
    /// </summary>
    public XRibbonPanel()
    {
        InitializeComponent();
        _contentPanel = xp.ContentPanel;
    }

    private void InitializeComponent()
    {
        this.EH = new System.Windows.Forms.Integration.ElementHost();
        this._xp = new TestRibbonPanel.RibbonPanel.XamlRibbonPanel();
        this.SuspendLayout();
        // 
        // EH
        // 
        this.EH.Dock = System.Windows.Forms.DockStyle.Fill;
        this.EH.Location = new System.Drawing.Point(0, 0);
        this.EH.Name = "EH";
        this.EH.Size = new System.Drawing.Size(150, 150);
        this.EH.TabIndex = 0;
        this.EH.Text = "";
        this.EH.Child = _xp;
        // 
        // XRibbonPanel
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.Controls.Add(this.EH);
        this.Name = "XRibbonPanel";
        this.ResumeLayout(false);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && (_components != null))
        {
            _components.Dispose();
        }
        EH.Dispose();
        base.Dispose(disposing);
    }
}

Как видите, я использовал пользовательский конструктор для элемента управления в надежде раскрыть элемент управления для дизайна.Это техника, которую я прочитал здесь и успешно применил для других «классических» элементов управления:

    using System;
using System.ComponentModel;
using System.Windows.Forms.Design;

namespace TestRibbonPanel
{
    public class XRibbonPanelDesigner : ScrollableControlDesigner
    {
        XRibbonPanel _panel;
        public override void Initialize(IComponent component)
        {
            base.Initialize(component);
            _panel = (XRibbonPanel)component;

            if (_panel == null)
                throw new ArgumentException();
            else
            {
                System.Windows.Forms.Panel pnl = _panel.ContentPanel;
                if (pnl != null)
                {
                    bool result = EnableDesignMode(pnl, "Layout");
                }
            }
        }
    }
}

Когда я помещаю XRibbonPanel в форму, панель действует как нужно (открывающаяся и закрывающаяся панель).Но, к сожалению, я не вижу объект «Макет», который я обычно использую для удаления вложенных элементов управления.Еще один неприятный эффект, когда я перемещаю форму, всплывающее окно Xaml Control всплывает на рабочем столе, отделенное от исходной формы.Это также происходит в режиме конструктора, когда я, например, оставляю вкладку формы открытой.

Если я установил точку останова на:

bool result = EnableDesignMode(pnl, "Layout"); 

в конструкторе, pnl не будет нулевым и логический результатверно.

Любая подсказка?

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