2011-12-22 14 views
6

एक wpf-application की कल्पना करें जहां मैं थीम को गतिशील रूप से बदल सकता हूं। मैं संसाधन-संसाधन स्तर पर संसाधन शब्दकोश को स्वैप करके ऐसा करता हूं। विषय-संसाधनों में टेक्स्टबॉक्स और इसी तरह के लिए परिभाषित अंतर्निहित शैलियों हैं।विषय-शैली/विकल्प से अलग-अलग स्थानीय अंतर्निहित शैली को अलग-अलग आधारित डायनामिक रिसोर्स

अब मेरे पास मेरे एप्लिकेशन में एक हिस्सा है जहां टेक्स्टबॉक्स में यह विशिष्ट शैली "NonDefaultTextBoxStyle" होनी चाहिए और एप्लिकेशन व्यापक रूप से अंतर्निहित नहीं है।

मैं यह करने के प्यार होता (DynamicResource का उपयोग कर, क्योंकि विषय रनटाइम के दौरान बदला जा सकता है):

<StackPanel> 
    <StackPanel.Resources> 
     <Style TargetType="TextBox" BasedOn="{DynamicResource NonDefaultTextBoxStyle}"/> 
    </StackPanel.Resources> 
    <TextBox .../> 
    <TextBox .../> 
    <TextBox .../> 
</StackPanel> 
बजाय यह करने के लिए होने के

:

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

अब इस आसान बनाने के लिए, मैं StackPanel पर एक विरासत संलग्न संपत्ति सेट करने का यह विचार था जो प्रत्येक वंशज टेक्स्टबॉक्स पर एक निर्दिष्ट शैली निर्धारित करेगा।

क्या यह एक अच्छा विचार है? क्या सरल तरीके हैं? क्या मैं कुछ भूल रहा हूँ?

इस

काफी करने पर निर्भर करता: क्या एक शैली में = "{DynamicResource ...} basedon लिए एक विकल्प है

उत्तर

4

मैं ठीक उसी समस्या थी लेकिन ItemsContainerStyle के लिए ... इसलिए मैंने क्या किया? ।

: काफी जो आपने कहा है और एक AttachedProperty कि basedon के लिए एक गतिशील संसाधन की अनुमति होगी लिखा

DynamicResource for Style BasedOn

यहाँ समाधान अपनी स्थिति के लिए संशोधित किया है 0

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; 
    } 
} 

और यहाँ इसके उपयोग का एक उदाहरण है:

<!-- 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

मैं केवल प्रश्न पढ़ने के लिए प्रोत्साहित कर सकते हैं! तुम मेरी समस्या को हल नहीं कर रहे हो! –

+0

@ MarkusHütter Ah मैं अब आपका प्रश्न देखता हूं। हम्म अच्छी तरह से मेरे उत्तर के साथ जारी है, आप 'फ्रेमवर्कप्रॉपर्टी मेटाडेटाऑप्शन। इनहेरिट्स' के लिए अपने समाधान में संलग्न निर्भरता गुणों को बदलने में सक्षम होना चाहिए (इस http://msdn.microsoft.com/en-us/library/ms557296.aspx के बजाय ' UIPropertyMetadata') और उसके बाद तत्व प्रकार 'StylesChanged' फ़ंक्शन की जांच करें। अटैचमेंट प्रॉपर्टी को केवल स्टैकपैनल तत्व पर एक बार लिखा जाना चाहिए। – NtscCobalt

+0

तो आपका मतलब है कि मैंने पहले से ही प्रश्न में क्या सुझाव दिया है ... –

3

यह वास्तव में एक DynamicResource होने की जरूरत है?
तो शायद this आप

में मदद मिलेगी अगर यहाँ नहीं 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> 

अगर दोनों आप शायद है मदद नहीं करता है आप प्रदान कर सकता है कि कैसे आप अपने संसाधन

संपादित

ठीक है कि अब आपके सवाल का

अनुप्रयोग में उत्तर देना चाहिए जोड़ें।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

मुझे आश्चर्य है कि यह एकमात्र प्रश्न क्यों है जिसे मैंने पोस्ट किया, जहां लोग सवाल नहीं पढ़ते! क्या विषय और समस्या को समझना बहुत मुश्किल है? आपको जवाब देने के लिए: हां, "गतिशील रूप से थीम को बदलने" (1 वाक्य) के लिए मेरी आवश्यकता के कारण इसे एक डायनामिक रिसोर्स होना चाहिए। यदि आप अपने लिंक किए गए प्रश्न को पढ़ लेंगे तो आपने देखा होगा कि उत्तर जैसे ही आपका उत्तर गतिशील संसाधन का उपयोग नहीं करता है। क्षमा करें, यह मदद नहीं करता है! –

+0

@ MarkusHütter क्षमा करें क्योंकि काफी अच्छी तरह से पढ़ा नहीं जाता है। शायद आपको इसे आंख पकड़ने वाले – WiiMaxx

+0

@ मार्कसहटर के रूप में बोल्ड करना चाहिए, मुझे लगता है कि मेरा संपादन अब आपके प्रश्न का उत्तर देगा – WiiMaxx

संबंधित मुद्दे