2017-10-18 89 views
-2

我已经创建了客户窗口(titlebar,min/max/ext按钮,自己的窗口操作边框以及大量样式和触发器)。如何重用WPF客户窗口

有定义的5种方法(我想重写):

从窗口标记:

SourceInitialized="Window_SourceInitialized" 

Closing="Window_Closing" 

从标题栏按钮:

Exit_Click() 

Max_Click() 

Min_Click() 

,最后我有DockPanel

<DockPanel Name="ClientArea"/> 

在这我希望把我的内容

我试图从代码中添加内容:

BaseWindow editInterfaceWindow = new BaseWindow() { Owner = this };     
editInterfaceWindow.DataContext = new EditInterface(); 
editInterfaceWindow.ShowDialog(); 

但是这样一些绑定采空工作和内部editInterfaceWindow我不能创建另一个窗口这种方式,因为Owner = this 。构造函数中的InitializeComponent()也存在一些问题。 而在EditInterface UserControl <ListView Name="LBAvaliable" ItemsSource="{Binding AvaliableFaces, UpdateSourceTrigger=PropertyChanged}">中的ListView在代码中不可见作为LBAvaliable。

我已经多次使用该窗口,手动填充ClientArea的内容。 我应该如何创建其他窗口,以便我可以继承它或只是定义绑定?所以我的每个窗口的XAML都不需要〜1000行代码。

+0

我不熟悉继承WPF中的窗口,但看看UserControls。它允许您重新使用现有的自定义控件。 –

+0

我的例子中的EditInterface实际上是UserControl和我试图做的 – Iluvatar

+0

一种方法是创建一个从基类窗口类继承的空的干净类,在那里添加你的方法(我认为你甚至可以使它们抽象)然后让你的实际窗口继承自* that *类而不是基类窗口类。 –

回答

1

以前我用过MVVMCross Framework,我们从来不用担心这个。虽然这不是最好的,但这里有一个关于你能做什么的想法。

  1. 创建一个可以被用户控件覆盖的视图模型。
  2. 设置数据模板。
  3. 以编程方式更改用户控件主要内容的视图模型,并让数据模板为UI执行工作。

查看模型:预定义的3个按钮动作可供您​​设置/覆盖。

public class MainUCViewModel : ViewModelBase 
{ 
    private Action<object> btnACommand; 
    private Action<object> btnBCommand; 
    private Action<object> btnCCommand; 

    private object ccVM; 

    public ViewModelBase CCVM 
    { 
     get { return this.ccVM; } 
     set 
     { 
      this.ccVM = value; 
      OnPropertyChanged(); // Notify View 
     } 
    } 

    public MainUCViewModel() 
    { 

    } 

    public RelayCommand BtnACommand 
    { 
     get { return new RelayCommand(btnACommand); } 
    } 

    public RelayCommand BtnBCommand 
    { 
     get { return new RelayCommand(btnBCommand); } 
    } 

    public RelayCommand BtnCCommand 
    { 
     get { return new RelayCommand(btnCCommand); } 
    } 

    public void SetBtnACommand(Action<object> action) 
    { 
     this.btnACommand = action; 
    } 

    public void SetBtnBCommand(Action<object> action) 
    { 
     this.btnBCommand = action; 
    } 

    public void SetBtnCCommand(Action<object> action) 
    { 
     this.btnCCommand = action; 
    } 
} 

查看:

<UserControl x:Class="WpfApplication1.Views.UserControls.MainUC" 
      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="500" d:DesignWidth="750"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="45" /> 
      <RowDefinition Height="*" /> 
     </Grid.RowDefinitions> 
     <Grid Grid.Row="0"> 
      <StackPanel Orientation="Horizontal"> 
       <Button Command="{Binding BtnACommand}" Width="100"> 
        <TextBlock>A</TextBlock> 
       </Button> 
       <Rectangle Width="15" /> 
       <Button Command="{Binding BtnBCommand}" Width="100"> 
        <TextBlock>B</TextBlock> 
       </Button> 
       <Rectangle Width="15" /> 
       <Button Command="{Binding BtnCCommand}" Width="100"> 
        <TextBlock>C</TextBlock> 
       </Button> 
      </StackPanel> 
     </Grid> 
     <Grid Grid.Row="1"> 
      <ContentControl x:Name="CCMain" Content="{Binding CCVM}"/> 
     </Grid> 
    </Grid> 
</UserControl> 

Thinking with MVVM: Data Templates + ContentControl。只需为您的视图模型定义数据模板即可。

<Window.Resources> 
    <DataTemplate DataType="{x:Type ViewModel:GeneralSettingsViewModel}"> 
     <View:GeneralSettingsView/> 
    </DataTemplate 
    <DataTemplate DataType="{x:Type ViewModel:AdvancedSettingsViewModel}"> 
     <View:AdvancedSettingsView/> 
    </DataTemplate> 
</Window.Resources> 

什么,我想说的是,GeneralSettingsViewModel应该使用GeneralSettingsView呈现 。这正是我们需要的! 因为Views是使用DataTemplate创建的,所以我们不需要 设置DataContext,它会自动注册到 模板对象ViewModel。

+0

我认为你可以回答我的问题,但给我更多的时间来测试 – Iluvatar

+0

@Ivvatar我刚刚完成测试这一个,它的工作。注意对' –

0

主要有两种方法,您的问题是:

  1. 继承的Windows
  2. 配置的Windows

对于方法1,设计你的窗口,使方法覆写投放:

在基本窗口xaml中,分配处理程序和所需的所有内容:

<Window x:Class="WpfTests.MainWindow" 
    ... 
    SourceInitialized="Window_SourceInitialized"> 

在基本窗口,定义为处理protected virtual(或abstract,如果你想强制其执行)

public partial class MainWindow : Window 
{ 
    // ... 

    protected virtual void Window_SourceInitialized(object sender, EventArgs e) 
    { 

    } 

    // ... 
} 

创建派生窗口

public class ExWindow : MainWindow 
{ 
    protected override void Window_SourceInitialized(object sender, EventArgs e) 
    { 
     // specialized code here 
    } 
} 

变化App.xaml中使用Startup而不是StartupUri

<Application x:Class="WpfTests.App" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Startup="Application_Startup"> 

并手动创建你的第一个窗口,艇员选拔继承窗口类

public partial class App : Application 
{ 
    private void Application_Startup(object sender, StartupEventArgs e) 
    { 
     var window = new ExWindow(); 
     window.Show(); 
    } 
} 

第二种方法之一 - 配置的Windows - 遵循相同的原则,良好的用户控制设计:窗口/控件属性由创建者控制而不是由窗口/控件本身控制。

所以,与其在窗口代码中定义一些事件处理程序,只要把这项工作给用户,谁希望知道的窗口应该做的:

public partial class MainWindow : Window 
{ 
    // I don't care for SourceInitialized (also remove it from XAML) 
} 

在App.xaml中或任何一个窗口创建:

public partial class App : Application 
{ 
    private void Application_Startup(object sender, StartupEventArgs e) 
    { 
     var window = new MainWindow(); 
     window.SourceInitialized += window_SourceInitialized; 
     window.Show(); 
    } 

    void window_SourceInitialized(object sender, EventArgs e) 
    { 
     var window = sender as MainWindow; 

     // I know how to handle this event for this window instance 
    } 
}