繁体   English   中英

如何在 WPF 主窗口的堆栈面板中打开新的 WPF window?

[英]how to open new WPF window in stack panel in WPF mainwindow?

我收到此错误:- System.NullReferenceException:“对象引用未设置为 object 的实例。” objectPlacement 为 null。

private void Button_Click(object sender, RoutedEventArgs e)
 {
    ObjectPlacement w = new ObjectPlacement() {Topmost = };// ObjectPlacement is new WPF window
    objectPlacement.WindowStyle = WindowStyle.None;
    settingpanel.Children.Add(objectPlacement);//settingpanel stack is panel name
    w.Show();
 }    

为您要在 window 中显示的内容定义用户控件或数据模板更为常见。window 是一种内容控件。 想到 window(或 contentcontrol)的一种方式是向您显示一些 UI。 window 中的所有 UI 都是该内容。

当您将 window 添加到项目时,它会被模板化,其中包含一个网格。 这就是 window 里面的内容和你想看到的一切。 您可以用其他东西替换该网格。

如果您将其设为 contentpresenter,那么您可以将其显示的内容绑定或设置为一些封装的可重用 UI。

通常封装可重用 UI 的最佳方式是作为用户控件。

数据模板可以引用用户控件。

通常,您要切换的不是 window 的整个 UI。 但是你可以,而且这偶尔有用——比如你想要一种通用的方式来显示对话框。

编写 wpf 的常用方法是 mvvm,因此大多数开发人员将需要一些 mvvm 方法来切换 UI。

我将向您展示一些代码可能会使描述更清楚。

以下内容有一些拐角,所以这是说明性的。 不要只是为了你在股票交易员的下一次首席开发人员面试而运行这个。 但是,基本上您单击一个登录按钮就可以“导航”到一个 LoginUC 视图。 单击用户按钮,您将“导航”到 UserUC。

我的主窗口。

    <Window.Resources>
        <DataTemplate DataType="{x:Type local:LoginViewModel}">
            <local:LoginUC/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:UserViewModel}">
            <local:UserUC/>
        </DataTemplate>
    </Window.Resources>
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <ItemsControl ItemsSource="{Binding NavigationViewModelTypes}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Content="{Binding Name}"
                        Command="{Binding DataContext.NavigateCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                        CommandParameter="{Binding VMType}"
                    />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <ContentPresenter Grid.Column="1"
                          Content="{Binding CurrentViewModel}"
                        />
    </Grid>
</Window>

注意将视图模型的类型与用户控件相关联的数据模板。 https://learn.microsoft.com/en-us/do.net/desktop/wpf/data/data-templating-overview?view.netframeworkdesktop-4.8

将发生的是您通过该内容呈现器和绑定将视图模型中的数据呈现给 UI。 然后将该视图模型作为数据上下文与您的视图模型一起模板化到 UI 中。 因此,UserUC 视图的数据上下文将是 UserViewModel 的一个实例。 将 CurrentViewModel 更改为 LoginViewModel 的一个实例,您将在主窗口中获得一个 LoginUC。

主视图模型。

public class MainWindowViewModel : INotifyPropertyChanged
{
    public string MainWinVMString { get; set; } = "Hello from MainWindoViewModel";

    public ObservableCollection<TypeAndDisplay> NavigationViewModelTypes { get; set; } = new ObservableCollection<TypeAndDisplay>
        (
        new List<TypeAndDisplay>
        {
           new TypeAndDisplay{ Name="Log In", VMType= typeof(LoginViewModel) },
           new TypeAndDisplay{ Name="User", VMType= typeof(UserViewModel) }
        }
        );

    private object currentViewModel;

    public object CurrentViewModel
    {
        get { return currentViewModel; }
        set { currentViewModel = value; RaisePropertyChanged(); }
    }
    private RelayCommand<Type> navigateCommand;
    public RelayCommand<Type> NavigateCommand
    {
        get
        {
            return navigateCommand
              ?? (navigateCommand = new RelayCommand<Type>(
                vmType =>
                {
                    CurrentViewModel = null;
                    CurrentViewModel = Activator.CreateInstance(vmType);
                }));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

类型和显示将视图模型的类型与 UI 中显示的文本相关联。

public class TypeAndDisplay
{
    public string Name { get; set; }
    public Type VMType { get; set; }
}

这是“只是”快速和肮脏的代码来说明通常称为视图模型优先导航的原则。 谷歌一下,你应该会找到一些进一步解释它的文章。

为了完整性:

<UserControl x:Class="wpf_Navigation_ViewModelFirst.LoginUC"
             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:local="clr-namespace:wpf_Navigation_ViewModelFirst"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <StackPanel Background="Yellow">
        <TextBlock Text="This is the Login User Control"/>
        <TextBox>
            <TextBox.InputBindings>
                <KeyBinding Key="Return" Command="{Binding LoginCommand}"/>
            </TextBox.InputBindings>
        </TextBox>
    </StackPanel>
</UserControl>

public  class LoginViewModel
{

private RelayCommand loginCommand;
public RelayCommand LoginCommand
{
    get
    {
        return loginCommand
          ?? (loginCommand = new RelayCommand(

            () =>
            {
                string s = "";
            }));
    }
}
}

<UserControl x:Class="wpf_Navigation_ViewModelFirst.UserUC"
             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:local="clr-namespace:wpf_Navigation_ViewModelFirst"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid Background="pink">
        <TextBlock Text="This is the User module Control"
                   VerticalAlignment="Top"
                   />
        <TextBlock Text="{Binding Path=DataContext.MainWinVMString, RelativeSource={RelativeSource  AncestorType={x:Type Window}}}"
                   VerticalAlignment="Bottom"
                   />
    </Grid>
</UserControl>

public class UserViewModel
{

}

几年前我把它放在一起,我现在推荐社区 mvvm 工具包及其代码生成、基类、信使等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM