2011-12-22 30 views
6

hãy tưởng tượng một ứng dụng wpf nơi tôi có thể thay đổi chủ đề động. Tôi làm điều này bằng cách hoán đổi ResourceDictionaries ở cấp Tài nguyên ứng dụng. Những người có nguồn gốc chủ đề có những phong cách ngầm định nghĩa cho TextBox và những thứ tương tự.Đặt kiểu ẩn cục bộ khác với kiểu chủ đề/thay thế thành BasedOn DynamicResource

Bây giờ tôi có một phần trong ứng dụng của tôi, nơi hộp văn bản nên có phong cách cụ thể này "NonDefaultTextBoxStyle" và không phải là ứng dụng tiềm ẩn rộng.

Tôi rất thích để làm điều này (sử dụng DynamicResource vì chủ đề có thể được thay đổi trong thời gian chạy):

<StackPanel> 
    <StackPanel.Resources> 
     <Style TargetType="TextBox" BasedOn="{DynamicResource NonDefaultTextBoxStyle}"/> 
    </StackPanel.Resources> 
    <TextBox .../> 
    <TextBox .../> 
    <TextBox .../> 
</StackPanel> 

thay vì phải làm điều này:

<StackPanel> 
    <TextBox Style="{DynamicResource NonDefaultTextBoxStyle}" .../> 
    <TextBox Style="{DynamicResource NonDefaultTextBoxStyle}" .../> 
    <TextBox Style="{DynamicResource NonDefaultTextBoxStyle}" .../> 
</StackPanel> 

Bây giờ để đơn giản hóa này, tôi đã có ý tưởng về việc thiết lập một thuộc tính được thừa kế có thể thừa kế trên StackPanel, nó sẽ thiết lập một kiểu được chỉ định trên mỗi hộp văn bản con cháu.

Đây có phải là một ý tưởng hay không? Có cách nào đơn giản hơn không? Tui bỏ lỡ điều gì vậy?

này khá nhiều boils xuống: một thay thế cho Basedon = "{DynamicResource ...} trong một phong cách là gì

Trả lời

4

tôi đã có vấn đề chính xác cùng nhưng đối với ItemsContainerStyle ... vì vậy tôi đã làm? . khá nhiều những gì bạn nói và viết một AttachedProperty mà sẽ cho phép một nguồn tài nguyên năng động cho Basedon

DynamicResource for Style BasedOn

đây sự là giải pháp sửa đổi cho tình hình của bạn:

public class DynamicStyle 
{ 
    public static Style GetBaseStyle(DependencyObject obj) 
    { 
     return (Style)obj.GetValue(BaseStyleProperty); 
    } 

    public static void SetBaseStyle(DependencyObject obj, Style value) 
    { 
     obj.SetValue(BaseStyleProperty, value); 
    } 

    // Using a DependencyProperty as the backing store for BaseStyle. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty BaseStyleProperty = 
     DependencyProperty.RegisterAttached("BaseStyle", typeof(Style), typeof(DynamicStyle), new UIPropertyMetadata(DynamicStyle.StylesChanged)); 

    public static Style GetDerivedStyle(DependencyObject obj) 
    { 
     return (Style)obj.GetValue(DerivedStyleProperty); 
    } 

    public static void SetDerivedStyle(DependencyObject obj, Style value) 
    { 
     obj.SetValue(DerivedStyleProperty, value); 
    } 

    // Using a DependencyProperty as the backing store for DerivedStyle. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty DerivedStyleProperty = 
     DependencyProperty.RegisterAttached("DerivedStyle", typeof(Style), typeof(DynamicStyle), new UIPropertyMetadata(DynamicStyle.StylesChanged)); 

    private static void StylesChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 
    { 
     if (!typeof(FrameworkElement).IsAssignableFrom(target.GetType())) 
      throw new InvalidCastException("Target must be FrameworkElement"); 

     var Element = (FrameworkElement)target; 

     var Styles = new List<Style>(); 

     var BaseStyle = GetBaseStyle(target); 

     if (BaseStyle != null) 
      Styles.Add(BaseStyle); 

     var DerivedStyle = GetDerivedStyle(target); 

     if (DerivedStyle != null) 
      Styles.Add(DerivedStyle); 

     Element.Style = MergeStyles(Styles); 
    } 

    private static Style MergeStyles(ICollection<Style> Styles) 
    { 
     var NewStyle = new Style(); 

     foreach (var Style in Styles) 
     { 
      foreach (var Setter in Style.Setters) 
       NewStyle.Setters.Add(Setter); 

      foreach (var Trigger in Style.Triggers) 
       NewStyle.Triggers.Add(Trigger); 
     } 

     return NewStyle; 
    } 
} 

Và đây là một ví dụ về sử dụng của mình:

<!-- xmlns:ap points to the namespace where DynamicStyle class lives --> 
<Button ap:DynamicStyle.BaseStyle="{DynamicResource {x:Type Button}}"> 
    <ap:DynamicStyle.DerivedStyle> 
     <Style TargetType="Button"> 
      <Style.Triggers> 
       <MultiDataTrigger> 
        <MultiDataTrigger.Conditions> 
         <Condition Binding="{Binding Path=FirstButtonWarning}" Value="True"/> 
         <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="True"/> 
        </MultiDataTrigger.Conditions> 
        <MultiDataTrigger.Setters> 
         <Setter Property="Background" Value="{DynamicResource WarningBackground}"/> 
         <Setter Property="Foreground" Value="{DynamicResource WarningForeground}"/> 
        </MultiDataTrigger.Setters> 
       </MultiDataTrigger> 
      </Style.Triggers> 
     </Style> 
    </ap:DynamicStyle.DerivedStyle> 
    <TextBlock Text="Button that changes background and foreground when warning is active"/> 
</Button> 
+0

Tôi chỉ có thể khuyên bạn nên đọc các câu hỏi! Bạn không giải quyết được vấn đề của tôi! –

+0

@ MarkusHütter Ah Tôi thấy câu hỏi của bạn ngay bây giờ. Hmm cũng tiếp tục với câu trả lời của tôi, bạn sẽ có thể thay đổi Thuộc tính Depenedencies đính kèm trong giải pháp của tôi thành 'FrameworkPropertyMetadataOptions.Inherits' (sử dụng http://msdn.microsoft.com/en-us/library/ms557296.aspx này thay vì' UIPropertyMetadata') và sau đó kiểm tra các loại phần tử 'StylesChanged' chức năng. Thuộc tính đính kèm sau đó sẽ chỉ cần được viết một lần trên phần tử StackPanel. – NtscCobalt

+0

vì vậy bạn có ý nghĩa như những gì tôi đã đề xuất trong câu hỏi ... –

3

hiện nó thực sự cần là một DynamicResource?
như vậy có lẽ this sẽ giúp bạn

nếu không muốn nói đây là một ví dụ đơn giản cho StaticResource

App.xaml

<Application.Resources> 
     <Style x:Key="myResource" TargetType="Button"> 
      <Setter Property="Background" Value="Black"/> 
      <Setter Property="Foreground" Value="White"/> 
     </Style>   
    </Application.Resources> 

MainWindow.xaml

<StackPanel> 
    <StackPanel.Resources> 
     <Style TargetType="Button" BasedOn="{StaticResource myResource}"/> 
    </StackPanel.Resources> 
    <Button Content="blubb" Height="23" Width="75" /> 
</StackPanel> 

nếu cả hai không giúp là bạn có thể bạn có thể cung cấp như thế nào bạn thêm tài nguyên của bạn

Sửa

ok bây giờ mà nên trả lời câu hỏi của bạn

App.XAML

<Application.Resources> 

    <SolidColorBrush x:Key="background" Color="Red" /> 
    <SolidColorBrush x:Key="foreground" Color="Blue" /> 

    <Style x:Key="NonDefaultTextBoxStyle" > 
     <Setter Property="TextBox.Background" Value="{DynamicResource background}"/> 
     <Setter Property="TextBox.Foreground" Value="{DynamicResource foreground}"/> 
    </Style> 

</Application.Resources> 

MainWindow.xaml

<StackPanel> 
    <Button Content="Button" Height="23" Width="75" Click="Button_Click" /> 

    <StackPanel> 
     <StackPanel.Resources> 
      <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource NonDefaultTextBoxStyle}"> 
      </Style> 
     </StackPanel.Resources> 
     <TextBox Text="bliii" Height="23" Width="75" /> 
     <TextBox Text="blaaa" Height="23" Width="75" /> 
     <TextBox Text="blubb" Height="23" Width="75" /> 
    </StackPanel> 

</StackPanel> 

MainWindow.cs

private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      this.Resources["background"] = Brushes.Black; 
      this.Resources["foreground"] = Brushes.Yellow; 
     } 
+0

Tôi tự hỏi tại sao đây là câu hỏi duy nhất tôi đăng, nơi mọi người không đọc câu hỏi! Chủ đề và vấn đề có quá khó hiểu không? để trả lời bạn: có, nó cần phải là một DynamicResource do yêu cầu của tôi để "tự động thay đổi chủ đề" (câu 1). Nếu bạn đọc câu hỏi được liên kết của mình, bạn sẽ nhận thấy rằng câu trả lời giống như câu trả lời của bạn không sử dụng tài nguyên động. Xin lỗi, điều này không giúp được gì! –

+0

@ MarkusHütter xin lỗi vì đã không đọc đủ kỹ lưỡng. Có lẽ bạn nên đậm nó như mắt catcher – WiiMaxx

+0

@ MarkusHütter tôi nghĩ rằng Chỉnh sửa của tôi bây giờ sẽ trả lời câu hỏi của bạn – WiiMaxx

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