2009-01-10 29 views
58

Tôi đang cố gắng đặt Kiểu mặc định cho mọi cửa sổ trong ứng dụng Windows WPF của tôi trong app.xaml của mình. Cho đến nay tôi có điều này trong App.xaml:Làm cách nào để đặt kiểu cửa sổ WPF mặc định trong app.xaml?

<Application.Resources> 
    <ResourceDictionary> 
     <Style x:Key="WindowStyle" TargetType="{x:Type Window}"> 
      <Setter Property="Background" Value="Blue" /> 
     </Style> 
    </ResourceDictionary> 
</Application.Resources> 

tôi có thể nhận được cửa sổ xuất hiện với phong cách này khi chạy ứng dụng (nhưng không phải là VS thiết kế) bằng cách đặc biệt nói với cửa sổ để sử dụng phong cách này qua:

Style="{DynamicResource WindowStyle} 

Công trình này, nhưng không lý tưởng. Vì vậy, làm cách nào để tôi:

  1. Có tất cả các cửa sổ tự động sử dụng kiểu (vì vậy tôi không phải chỉ định cửa sổ trên mọi cửa sổ)?
  2. Trình thiết kế VS có hiển thị kiểu không?

Cảm ơn!

Trả lời

8

Nhà thiết kế không hoạt động vì bạn đang chỉ định DynamicResource. Vui lòng thay đổi điều này thành StaticResource và tất cả sẽ tốt.

Để áp dụng cho tất cả các cửa sổ, bạn nên xóa khóa x: khỏi kiểu. Đặt TargetType ngầm định đặt x: Key thành bất kỳ thứ gì trong TargetType. Tuy nhiên, trong các thử nghiệm của tôi, điều này không hoạt động, vì vậy tôi đang xem xét nó.

Nếu tôi đặt TargetType thành x: Loại TextBlock, trình thiết kế hoạt động hoàn hảo, dường như cửa sổ đang hiển thị hành vi khác.

+1

Vâng, tôi chỉ gặp phải vấn đề tương tự. Gishu nói ở trên rằng có vẻ như phong cách tiềm ẩn cho Window sẽ không áp dụng cho cửa sổ của bạn, vì nó thực sự là một lớp dẫn xuất. –

45

Để thêm vào những gì Ray nói:

Đối với Styles, bạn có cần phải cung cấp một khóa/ID hoặc chỉ định một TargetType.

Nếu một FrameworkElement không có một quy định một cách rõ ràng Style, nó sẽ luôn tìm kiếm một nguồn tài nguyên Style, sử dụng loại riêng của mình như là chìa khóa
- Lập trình WPF (Sells, Griffith)

Nếu bạn cung cấp TargetType, tất cả các trường hợp thuộc loại đó sẽ có kiểu được áp dụng. Tuy nhiên các loại có nguồn gốc sẽ không ... có vẻ như. <Style TargetType="{x:Type Window}"> sẽ không hoạt động đối với tất cả các mục nhập/cửa sổ tùy chỉnh của bạn. <Style TargetType="{x:Type local:MyWindow}"> sẽ chỉ áp dụng cho MyWindow. Vì vậy, các tùy chọn là

  • Sử dụng một Style Keyed mà bạn chỉ định là tài sản Phong cách của mỗi cửa sổ bạn muốn áp dụng phong cách. Nhà thiết kế sẽ hiển thị cửa sổ theo kiểu.

.

<Application.Resources> 
     <Style x:Key="MyWindowStyle"> 
      <Setter Property="Control.Background" Value="PaleGreen"/> 
      <Setter Property="Window.Title" Value="Styled Window"/> 
     </Style> 
    </Application.Resources> ... 
    <Window x:Class="MyNS.MyWindow" Style="{StaticResource MyWindowStyleKey}"> ... 
  • Hoặc bạn có thể bắt nguồn từ một lớp tùy chỉnh BaseWindow (trong đó có its own quirks), nơi bạn thiết lập thuộc tính Phong cách trong ctor/Khởi tạo/Load sân khấu một lần. Tất cả các dẫn xuất sau đó sẽ tự động áp dụng kiểu. Nhưng nhà thiết kế sẽ không chú ý đến phong cách của bạn Bạn cần chạy ứng dụng của mình để xem kiểu đang được áp dụng ..Tôi đoán các nhà thiết kế chỉ cần chạy InitializeComponent (đó là tự động/thiết kế tạo ra mã) để XAML được áp dụng nhưng không tùy chỉnh mã phía sau.

Vì vậy, tôi muốn nói kiểu được chỉ định rõ ràng là công việc ít nhất. Bạn có thể thay đổi các khía cạnh của Style ở giữa.

+2

Dòng cuối cùng " Anthony

+0

Bạn có thể 'xếp tầng' phong cách bằng cách sử dụng thuộc tính BasedOn. 'BasedOn =" {StaticResource {x: Type Window}} "' Tuy nhiên, tôi không thể lấy Window chấp nhận kiểu không khóa.Tôi đoán đó là bởi vì họ không nhận ra các loại có nguồn gốc, như bạn đã nói. –

+0

Mã của bạn có đầy đủ các lỗi và thậm chí không đến gần biên dịch và có hiệu quả vô dụng, ví dụ bằng cách sử dụng 'MyWindowStyleKey' và' MyWindowStyle'. Một trong nhiều lý do tại sao gần 9 năm sau nó đã không được chấp nhận. – Matt

18

biết đây là năm sau, nhưng kể từ khi câu hỏi vẫn là lên đây ...

  1. Tạo một từ điển tài nguyên trong dự án của bạn (Kích chuột phải vào dự án ...)

    tôi sẽ tạo một thư mục mới theo dự án được gọi là 'Tài sản' và đặt "resourceDict.XAML trong đó

  2. Thêm mã để resourceDict.XAML:.

    <Style x:Key="WindowStyle" Target Type="Window" > 
        <Setter Property="Background" Value="Blue" /> 
    </Style> 
    
  3. Trong file XAML dự án của bạn thêm dòng sau dưới cửa sổ:

    <Window.Resources> 
        <ResourceDictionary> 
         <!-- Believe it or not the next line fixes a bug MS acknowledges --> 
         <Style TargetType="{x:Type Rectangle}" /> 
         <ResourceDictionary.MergedDictionaries> 
          <ResourceDictionary Source="/Assets/resourceDict.XAML" /> 
         </ResourceDictionary.MergedDictionaries> 
        <ResourceDictionary> 
    </Window.Resources> 
    

    ref trang web sau đây: Trouble referencing a Resource Dictionary that contains a Merged Dictionary "Có một lỗi: nếu tất cả các kiểu mặc định của bạn được lồng trong từ điển sáp nhập ba cấp độ sâu (hoặc sâu hơn) từ điển hàng đầu không bị gắn cờ để tìm kiếm bỏ qua nó. Công việc xung quanh là để đặt một phong cách mặc định cho một cái gì đó, bất cứ điều gì, trong từ điển gốc. " Và nó dường như ... Điện thoại

  4. Và cuối cùng, trong Window, có thể sau Tiêu đề, nhưng trước khi Window thức '>':.

    Style="{DynamicResource windowStyle}" 
    
  5. Và bạn sẽ cần phải thêm mã trong bước 3 & 4 đến từng dự án mà bạn muốn phong cách để áp dụng

  6. Nếu bạn muốn để sử dụng nền gradient thay vì màu đồng nhất, hãy thêm cá tuyết sau e đến resourceDict.XAML:

    <LinearGradientBrush x:Key="windowGradientBackground" StartPoint="0,0" 
         EndPoint="0,1" > 
    <GradientStop Color= "AliceBlue" Offset="0" /> 
    <GradientStop Color= "Blue" Offset=".75" /> 
    </LinearGradientBrush> 
    
  7. Và sửa đổi Setter Phong cách của bạn cho màu nền để đọc:

    <Setter Property="Background" Value="{DynamicResource 
         windowGradientBackground}" /> 
    

bước 3 & 4 cần phải được lặp đi lặp lại trong mỗi project.XAML tập tin như mô tả ở trên, nhưng hey, bạn sẽ có được Windows thống nhất trên toàn bộ giải pháp! Và quá trình tương tự cũng có thể áp dụng cho bất kỳ điều khiển nào bạn muốn có một cái nhìn thống nhất, nút bấm, bất cứ điều gì.

Đối với bất cứ ai đến muộn, hy vọng điều này sẽ giúp tôi chắc chắn rằng các áp phích ban đầu có tất cả những điều này đã được tìm ra cách đây nhiều năm.

Paul

+0

Mẹo ở đây về việc không nhúng MergedDictionaries trong MergedDictionaries là giải pháp cho tôi. Đơn giản chỉ cần khai báo tất cả các tập tin chủ đề trực tiếp từ App.xaml Vì vậy, cảm ơn! –

1

Đối với những người này phải vật lộn với một giải pháp cho vấn đề: Làm thế nào tôi có thể có một phong cách tùy chỉnh được automtically áp dụng cho tất cả các cửa sổ có nguồn gốc loại của tôi? Dưới đây là giải pháp tôi đã đưa ra

LƯU Ý: Tôi thực sự không muốn lấy được từ loại Cửa sổ hoặc phải chèn XAML trên mỗi cửa sổ để buộc cập nhật kiểu, v.v.vì lý do cụ thể cho dự án của tôi (người tiêu dùng sản phẩm của tôi cho chúng tôi thư viện kiểu tái sử dụng chung của tôi và tạo bố cục/cửa sổ riêng của họ, v.v.) tôi đã thực sự động cơ để tìm ra giải pháp mà tôi sẵn sàng sống với bất kỳ bên nào hiệu ứng

Cần lặp qua tất cả các cửa sổ đã được khởi tạo và đơn giản buộc chúng sử dụng kiểu tùy chỉnh mới mà bạn đã xác định cho loại Cửa sổ. Điều này làm việc tuyệt vời cho các cửa sổ đã được lên nhưng khi một cửa sổ hoặc cửa sổ con được khởi tạo nó sẽ không biết sử dụng kiểu mới/tùy chỉnh đã được khai báo cho kiểu cơ sở của nó; loại cửa sổ vanilla. Vì vậy, tốt nhất tôi có thể đưa ra là sử dụng LostKeyBoardFocus trên MainWindow khi nó mất Focus đến ChildWindow (IOW Khi một cửa sổ con đã được tạo) và sau đó gọi ra FixupWindowDerivedTypes() này.

Nếu ai đó có giải pháp tốt hơn để "phát hiện" khi bất kỳ loại kiểu xuất phát cửa sổ nào được khởi tạo và do đó hãy gọi cho FixupWindowDerivedTypes() sẽ tuyệt vời. Có thể có điều gì đó hữu ích khi xử lý WM_WINDOWPOSCHANGING trong khu vực này.

Vì vậy, giải pháp này là không thanh lịch cho mỗi nói nhưng được công việc làm mà không cần tôi phải chạm vào bất kỳ mã hoặc XAML liên quan đến cửa sổ của tôi.

public static void FixupWindowDerivedTypes() 
    { 
     foreach (Window window in Application.Current.Windows) 
     { 
      //May look strange but kindly inform each of your window derived types to actually use the default style for the window type 

        window.SetResourceReference(FrameworkElement.StyleProperty, DefaultStyleKeyRetriever.GetDefaultStyleKey(window)); 
       } 
      } 
     } 
    } 


//Great little post here from Jafa to retrieve a protected property like DefaultStyleKey without using reflection. 
http://themechanicalbride.blogspot.com/2008/11/protected-dependency-properties-are-not.html 

//Helper class to retrieve a protected property so we can set it 
internal class DefaultStyleKeyRetriever : Control 
{ 
    /// <summary> 
    /// This method retrieves the default style key of a control. 
    /// </summary> 
    /// <param name="control">The control to retrieve the default style key 
    /// from.</param> 
    /// <returns>The default style key of the control.</returns> 
    public static object GetDefaultStyleKey(Control control) 
    { 
     return control.GetValue(Control.DefaultStyleKeyProperty); 
    } 
} 
-1
  1. bạn sẽ tiết kiệm tất cả các phong cách trong một tập tin XAML (ví dụ design.xaml)

  2. và sau đó gọi đó (design.xaml) tập tin XAML trong tất cả các trang như cách này

Giống như:

<ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="Design.xaml"/>     
</ResourceDictionary.MergedDictionaries> 
0

Xem xét câu trả lời của Gishu Tôi đã tìm ra một giải pháp khác. Nhưng nó có thể hơi lạ một chút. Nếu bạn sử dụng mẫu MVVM, bạn có thể loại bỏ mã-đằng sau cửa sổ của bạn và x: Đánh dấu lớp trong tệp XAML. Vì vậy, bạn sẽ nhận được một thể hiện của cửa sổ hoặc cửa sổ tùy chỉnh của bạn nhưng không phải là một ví dụ của lớp 'MainWindow' có nguồn gốc từ lớp 'Window' và được đánh dấu là một phần. Tôi đang tạo cửa sổ giống như VS nên tôi phải kế thừa lớp cửa sổ và mở rộng chức năng của nó. Trong trường hợp đó, nó sẽ có thể làm cho lớp cửa sổ mới là một phần mà sẽ cho phép chúng ta tạo mã sau mà không cần thừa kế.

2

tôi điều tra này cho một số ngày bây giờ và làm cho nó hoạt động thông qua các Constructor của tùy chỉnh cửa sổ lớp tôi:

public class KWindow : Window 
{ 
     public KWindow() 
     { 
      this.SetResourceReference(StyleProperty, typeof(KWindow)); 
     } 

     static KWindow() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(KWindow), new FrameworkPropertyMetadata(typeof(KWindow))); 

     } 

     public override void OnApplyTemplate() 
     { 
      base.OnApplyTemplate(); 

      // gets called finally 
     } 
} 

Hy vọng nó sẽ giúp người

1

Bạn có thể thêm mã này vào App.xaml của bạn file .cs:

 FrameworkElement.StyleProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata 
     { 
      DefaultValue = Application.Current.FindResource(typeof(Window)) 
     }); 

Sau này, phong cách áp dụng cho các loại Window cũng sẽ áp dụng cho tất cả các loại có nguồn gốc từ Window

+0

Đây là giải pháp duy nhất hoạt động cho lớp 'BaseWindow' của tôi. Cảm ơn bạn! – pinki

Các vấn đề liên quan