2011-09-21 78 views
2

是否有推薦的方式與WPF創建一個共同的窗口風格,以跨應用程序使用?我有幾個對話框出現在我的應用程序中,我希望它們的樣式都一樣(相同的窗口邊框,確定/取消按鈕位置等),根據具體情況,每個對象都有不同的「內容」。所以,一個對話框可能有一個列表框,其中可能有一個文本框,等等。如何創建一個通用的WPF基礎窗口樣式?

我明白如何製作基本的.cs用戶控制文件,但是我不能爲我的生活找到一個很好的方法來創建一個可以在啓動時託管不同內容的單個窗口?

乾杯, RJ

回答

15

一種方式做這將是一個新的自定義控制,我們稱之爲DialogShell

namespace Test.Dialogs 
{ 
    public class DialogShell : Window 
    { 
     static DialogShell() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(DialogShell), new FrameworkPropertyMetadata(typeof(DialogShell))); 
     } 
    } 
} 

現在,這需要這通常會在Themes/Generic.xaml定義模板,在那裏,你可以創建默認結構和綁定在Content

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:Test.Dialogs"> 
    <Style TargetType="{x:Type local:DialogShell}" BasedOn="{StaticResource {x:Type Window}}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type local:DialogShell}"> 
        <Grid Background="{TemplateBinding Background}"> 
         <Grid.RowDefinitions> 
          <RowDefinition /> 
          <RowDefinition Height="Auto" /> 
         </Grid.RowDefinitions> 
         <!-- This ContentPresenter automatically binds to the Content of the Window --> 
         <ContentPresenter /> 
         <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="5" HorizontalAlignment="Right"> 
          <Button Width="100" Content="OK" IsDefault="True" /> 
          <Button Width="100" Content="Cancel" IsCancel="True" /> 
         </StackPanel> 
        </Grid> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

這只是一個例子,你可能想掛鉤這些按鈕與自定義事件,您需要在CS-文件中定義的屬性。

這個shell則可以使用這樣的:

<diag:DialogShell x:Class="Test.Dialogs.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:diag="clr-namespace:Test.Dialogs" 
     Title="Window1" Height="300" Width="300"> 
    <Grid> 
     <TextBlock Text="Lorem Ipsum" /> 
    </Grid> 
</diag:DialogShell> 
namespace Test.Dialogs 
{ 
    public partial class Window1 : DialogShell 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
     } 
    } 
} 

事件連接的例子(不知道這是 「正確」 的做法雖然)

<Button Name="PART_OKButton" Width="100" Content="OK" IsDefault="True" /> 
<Button Name="PART_CancelButton" Width="100" Content="Cancel" IsCancel="True" /> 
namespace Test.Dialogs 
{ 
    [TemplatePart(Name = "PART_OKButton", Type = typeof(Button))] 
    [TemplatePart(Name = "PART_CancelButton", Type = typeof(Button))] 
    public class DialogShell : Window 
    { 
     //... 

     public DialogShell() 
     { 
      Loaded += (_, __) => 
       { 
        var okButton = (Button)Template.FindName("PART_OKButton", this); 
        var cancelButton = (Button)Template.FindName("PART_CancelButton", this); 
        okButton.Click += (s, e) => DialogResult = true; 
        cancelButton.Click += (s, e) => DialogResult = false; 
       }; 
     } 
    } 
} 
+0

感謝這似乎是讓我在正確的軌道上。如何將事件處理程序設置爲DialogShell.XAML中的按鈕?由於我無法將x:class應用於ResourceDictionary? –

+0

@RJLhan:你可以給按鈕分配名字,並通過在'Template'中再次找到它們來代替它們(ctor過早,'Loaded'事件起作用)。如果您只有OK&Cancel,您可能甚至不想公開這些按鈕的事件,因爲這些應該只是將'DialogResult'設置爲true或false。 (如果你這樣做使這些按鈕[模板部分](http://msdn.microsoft.com/en-us/library/system.windows.templatepartattribute.aspx),這樣的人誰創建的主題知道如何按鈕應該被命名) –

+0

@RJLohan:在我的答案中增加了一個例子。 –

0

您可以使用定義的App.xaml一種風格,針對所有窗口。

這是你的App.xaml中可以如何看起來像一個示例:

<Application x:Class="ES.UX.App" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     StartupUri="Views/MainWindow.xaml"> 
<Application.Resources> 
    <Style TargetType="Window"> 
     <Setter Property="WindowStyle" Value="ToolWindow" /> 
    </Style> 
</Application.Resources> 

然後你可能需要設置控件模板爲您窗口更高級的方案。

+0

謝謝,但在我的情況下,'風格'也包括佈局,所以這種方法並不會真正實現很多,因爲我仍然需要重新模板控件以在適當的位置提供內容。 –

1

要添加到HB的非常有用的文章,您可能想conn在加載的事件中處理事件處理程序,但是不要使用匿名方法或lambda表達式,而應考慮將它們連接到受保護的虛擬方法,如果功能需要改變,則可以在派生類中重寫該方法。就我而言,我創建了具有保存和取消按鈕的基本數據錄入形式:

public DataEntryBase() 
    { 
     Loaded += (_, __) => 
     { 
      var saveButton = (Button)Template.FindName("PART_SaveAndCloseButton", this); 
      var cancelButton = (Button)Template.FindName("PART_CancelButton", this); 
      saveButton.Click += SaveAndClose_Click; 
      cancelButton.Click += Cancel_Click; 
     }; 
    } 

    protected virtual void SaveAndClose_Click(object sender, RoutedEventArgs e) { DialogResult = true; } 

    protected virtual void Cancel_Click(object sender, RoutedEventArgs e) { } 

保存功能,然後在每一個派生類中重寫保存特定實體:

protected override void SaveAndClose_Click(object sender, RoutedEventArgs e) 
    { 
     if (Save()) 
     { 
      base.SaveAndClose_Click(sender, e); 
     } 
    } 

    private bool Save() 
    { 
     Contact item = contactController.SaveAndReturnContact((Contact)DataContext); 
     if (item!=null) 
     { 
      DataContext = item; 
      return true; } 
     else 
     { 
      MessageBox.Show("The contact was not saved, something bad happened :("); 
      return false; 
     }    
    } 
+0

'Close()'是多餘的,設置'DialogResult '關閉窗口 –

+0

雅,我發現有一段時間後...修改後的示例 – Erikest

0

創建XAML中表單模板和模板添加到VS安裝的ItemTemplate目錄。

1)創建一個wpf xaml和xaml.cs文件,該文件具有添加到應用程序中的新表單所需的所有組件。在我的情況下,我想要標題和工具欄按鈕。

2)通過當前的系統流測試新XAML文件。

3)將xaml/xaml.cs複製到臨時位置,並將兩個文件名都重命名爲您想要被識別爲好模板名稱的對象。 一)XAML文件中更改第一行 - 窗口x: 「$ rootnamespace $ $ $ safeitemname」 CLASS =

b)以xaml.cs文件中的3次修改,以確保新的名稱將被複制時使用模板 - - 命名空間$ rootnamespace $(//動態命名空間名稱) - 公共部分類$ safeitemname $(//動態類名稱) - public $ safeitemname $()(//動態構造函數名稱)

4)現在創建一個vstemplate文件:即。 MyTemplate.vstemplate具有以下內容:

<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Item"> 
    <TemplateData> 
    <DefaultName>WpfFormTemplate.xaml</DefaultName> 
    <Name>WpfFormTemplate</Name> 
    <Description>Wpf/Entities form</Description> 
    <ProjectType>CSharp</ProjectType> 
    <SortOrder>10</SortOrder> 
    <Icon>Logo.ico</Icon> 
    </TemplateData> 
    <TemplateContent> 
    <References> 
     <Reference> 
      <Assembly>System.Windows.Forms</Assembly> 
     </Reference> 
     <Reference> 
      <Assembly>Workplace.Data.EntitiesModel</Assembly> 
     </Reference> 
     <Reference> 
      <Assembly>Workplace.Forms.MainFormAssemb</Assembly> 
     </Reference> 
    </References> 
    <ProjectItem SubType="Designer" TargetFileName="$fileinputname$.xaml" ReplaceParameters="true">WpfFormTemplate.xaml</ProjectItem> 
    <ProjectItem SubType="Code" TargetFileName="$fileinputname$.xaml.cs" ReplaceParameters="true">WpfFormTemplate.xaml.cs</ProjectItem> 
    </TemplateContent> 
</VSTemplate> 

5)一旦你把所有這些文件,壓縮文件,並把zip文件下.... \文檔\的Visual Studio 2012 \模板\的ItemTemplate \ WPF目錄。現在,您可以進入VS2012並使用ADD \ New功能查看模板,並按照正常流程進行選擇和重命名。通過將zip文件放置在2010模板Wpf目錄下,可以以與VS2010相同的方式使用該模板。

徽標文件也應包含在zip文件中,或者如果您沒有文件,則從MyTemplate.vstemplate文件中刪除該行。

+0

我不確定這是一個共享/共同的基本窗口,這聽起來就像它只是一個模板,可以有效地將代碼粘貼到新窗口中? –

相關問題