如何将WPF UserControl 从一个窗口移动到另一个窗口?

6
假设我有一个名为MyVideoControl的UserControl,它位于MainWindow.xaml中:
<Window Name="_mainWindow">
    <Grid>
        <MyVideoControl Name="_localVideo"/>
    </Grid>
</Window>

现在用户点击按钮时,我希望用户控件浮动在MainWindow.xaml的顶部,放在一个新创建的名为PopUp.xaml的窗口中。
<Window Name="_popUpWindow">
    <Grid>
        <MyVideoControl Name="_localVideo"/>
    </Grid>
</Window>

如何实现整个对象的移动?目前我使用XAML在窗口中声明性地放置MyVideoControl,但我猜想我需要通过编程来完成所有操作?


我认为这是不可能的。你在其他地方看到过这种功能吗?我非常确定所有控件必须包含在一个(且仅一个)窗口中。 - Jras
1
当用户单击按钮时,您可以从主窗口中删除用户控件并将其添加到新窗口。 - KF2
@Jras - 或许我表达不够清楚。该控件在任何时候都将包含在一个(且仅一个)窗口中。因此,在某一时间点,它将是MainWindow,但在另一时间点,它将是PopUpWindow。只有一个实例,但它会在这两个窗口之间移动。 - Eternal21
@Eternal21 我对"浮动在MainWindow.xaml之上"这个措辞感到困惑。当读到这句话时,我想象控件实际上离开窗口,并通过某种WPF过渡效果浮动到新窗口中。 - Jras
3个回答

12

您可以通过将UserControlMainWindow中移除,并将其作为逻辑子元素添加到PopupWin窗口中的任何控件中来实现此目的。

enter image description here

UserControl.xaml:

<UserControl x:Class="WpfApplication1.UserControl1"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="100">
    <Grid>
        <TextBox x:Name="txtBlock1" Text="hai"/>
    </Grid>
</UserControl>

MainWindow.xaml :

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WpfApplication1="clr-namespace:WpfApplication1" Title="MainWindow" Height="550" Width="555">
    <Grid>
        <StackPanel x:Name="mainPanel" Orientation="Vertical ">
            <Button Content="Button" Height="23" Name="button1" Width="75" Click="button1_Click" />
            <WpfApplication1:UserControl1 x:Name="myUserControl" />
        </StackPanel>
    </Grid>
</Window>

PopupWin.xaml :

<Window x:Class="WpfApplication1.PopupWin"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="PopupWin" Height="300" Width="300">

    <StackPanel x:Name="mainPanel"/>

</Window>

PopupWin.xaml.cs:添加一个新的构造函数,接受userControl并将其作为子控件添加到mainPanel中。

public partial class PopupWin : Window
{
    public PopupWin()
    {
        InitializeComponent();
    }

    private UserControl control;

    public PopupWin(UserControl control)
        : this()
    {
        this.control = control;

        this.mainPanel.Children.Add(this.control);
    }
}

MainWindow.xaml.cs 在 Button_Click 事件中,将用户控件从当前的 MainWindow 中移除,并通过构造函数将其传递给 PopupWin

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        this.mainPanel.Children.Remove(this.myUserControl);

        var wind = new PopupWin(this.myUserControl);

        wind.ShowDialog();
    }

注意: userControl 实例应始终是一个元素的逻辑子元素,任何时候都只能是一个。


1
接受这个答案,因为它在仍然能够使用XAML的同时,不需要诉诸于资源字典,并且代码也很少,是一个不错的折中方案。 - Eternal21

1
如果您将UserControl作为资源使用,则可以这样做。
示例:

App.Xaml

<Application x:Class="WpfApplication10.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ContentControl x:Key="sharedContent">
            <Label Content="StackOverFlow" />
        </ContentControl>
    </Application.Resources>
</Application>

主窗口

<Window x:Class="WpfApplication10.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="325" Width="422" Name="UI">

    <StackPanel>
        <Button Content="Open PopUp" Click="Button_Click" />
        <ContentControl Content="{DynamicResource sharedContent}" />
    </StackPanel>
</Window>

弹出窗口。
<Window x:Class="WpfApplication10.PopupWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="PopupWindow" Height="300" Width="300" xmlns:my="clr-namespace:WpfApplication10">
    <Grid>
        <ContentControl Content="{DynamicResource sharedContent}" />
    </Grid>
</Window>

结果:

enter image description here enter image description here


1

另一种实现方式是使用动态布局...

 public partial class MainWindow : Window
{
    public Button ControlToMove { get; set; }

    public MainWindow()
    {
        InitializeComponent();

        //create button
        ControlToMove = new Button();

        //add text to button
        ControlToMove.Content = "Click to move me to pop up window";

        //add a new routed event to the buttons click property
        ControlToMove.Click += new RoutedEventHandler(MoveControlToPopUp);

        //add control to the layout grid
        MainGrid.Children.Add(ControlToMove);
    }

    //This method moves the button to a popup window
    private void MoveControlToPopUp(object sender, RoutedEventArgs e)
    {
        //get the name of the control from sender
        var control = sender as Button;
        var controlName = control.Name;

        //checks to see if this is the control we want moved
        //if its not, method exits
        if (controlName != ControlToMove.Name) return;

        //create copy of the control
        var copiedControl = control;

        //remove control from existing window
        MainGrid.Children.Remove(control);

        //create pop up window
        var popUpWindow = new PopUpWindow(copiedControl);
        popUpWindow.Show();
    }
}

public class PopUpWindow : Window
{
    public Grid Layout { get; set; }
    public PopUpWindow(Button button)
    {
        //create a grid for the new window
        Layout = new Grid();

        //add control to grid
        Layout.Children.Add(button);

        //add grid to window
        this.AddChild(Layout);
    }
}

}

我在那里唯一没有做的事情是添加能力,使按钮在弹出窗口中被点击后返回到主窗口。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接