WPF में कई शैलियों को कैसे लागू करें


153

WPF में, मैं एक से अधिक शैलियों को कैसे लागू करूंगा FrameworkElement? उदाहरण के लिए, मेरा एक नियंत्रण है जिसमें पहले से ही एक शैली है। मेरे पास एक अलग शैली भी है जिसे मैं पहले वाले को उड़ाए बिना इसे जोड़ना चाहूंगा। शैलियों में अलग-अलग लक्ष्य-चिह्न हैं, इसलिए मैं एक को दूसरे के साथ नहीं बढ़ा सकता।


ओपी ने कभी निर्दिष्ट नहीं किया कि क्या उसकी पहली शैली अकेले एकल नियंत्रण के लिए अद्वितीय है। इस पृष्ठ पर दिए गए उत्तर दोनों शैलियों को कई नियंत्रणों में साझा करने की आवश्यकता मानते हैं। यदि आप नियंत्रणों पर आधार शैलियों का उपयोग करने और व्यक्तिगत नियंत्रणों पर सीधे व्यक्तिगत गुणों को ओवरराइड करने का एक तरीका खोज रहे हैं: इस उत्तर को देखें: stackoverflow.com/a/54497665/1402498
JamesHoux

जवाबों:


154

मुझे लगता है कि सरल उत्तर यह है कि आप ऐसा नहीं कर सकते (कम से कम WPF के इस संस्करण में) जो आप करने की कोशिश कर रहे हैं।

यही है, किसी विशेष तत्व के लिए केवल एक स्टाइल लागू किया जा सकता है।

हालांकि, जैसा कि दूसरों ने ऊपर कहा है, शायद आप अपनी BasedOnमदद करने के लिए उपयोग कर सकते हैं । ढीले xaml के निम्नलिखित टुकड़े की जाँच करें। इसमें आप देखेंगे कि मेरे पास एक आधार शैली है जो एक ऐसी संपत्ति स्थापित कर रही है जो उस तत्व के आधार वर्ग पर मौजूद है जिसे मैं अपनी शैलियों को लागू करना चाहता हूं। और, दूसरी शैली में जो आधार शैली पर आधारित है, मैंने एक और संपत्ति निर्धारित की है।

तो, यहाँ विचार ... यदि आप किसी भी तरह से उन गुणों को अलग कर सकते हैं जिन्हें आप सेट करना चाहते हैं ... तत्व की विरासत पदानुक्रम के अनुसार आप कई शैलियों को सेट करना चाहते हैं ... तो आपके पास वर्कअराउंड हो सकता है।

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <Style x:Key="baseStyle" TargetType="FrameworkElement">
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
        <Style TargetType="Button" BasedOn="{StaticResource baseStyle}">
            <Setter Property="Content" Value="Hello World"/>
        </Style>
    </Page.Resources>
    <Grid>
        <Button Width="200" Height="50"/>
    </Grid>
</Page>


उम्मीद है की यह मदद करेगा।

ध्यान दें:

विशेष रूप से ध्यान देने योग्य एक बात। यदि आप TargetTypeदूसरी शैली (ऊपर के xaml के पहले सेट में) में बदलते हैं ButtonBase, तो दो शैलियाँ लागू नहीं होती हैं। हालाँकि, उस प्रतिबंध के आसपास पाने के लिए नीचे दिए गए xaml को देखें। मूल रूप से, इसका मतलब है कि आपको स्टाइल को एक कुंजी देने और उस कुंजी के साथ संदर्भ देने की आवश्यकता है।

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <Style x:Key="baseStyle" TargetType="FrameworkElement">
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
        <Style x:Key="derivedStyle" TargetType="ButtonBase" BasedOn="{StaticResource baseStyle}">
            <Setter Property="Content" Value="Hello World"/>
        </Style>
    </Page.Resources>
    <Grid>
        <Button Width="200" Height="50" Style="{StaticResource derivedStyle}"/>
    </Grid>
</Page>

10
याद रखें ... ** आदेश देना महत्वपूर्ण है **। के derivedStyleबाद आना चाहिएbaseStyle
SliverNinja - MSFT

50

बीओ स्टोलनिट्ज़ के पास इसके लिए एक मार्कअप एक्सटेंशन का उपयोग करने के बारे में एक अच्छा ब्लॉग पोस्ट था , शीर्षक के तहत "मैं WPF शैलियों में कई कैसे सेट कर सकता हूं?"

वह ब्लॉग अब मृत हो गया है, इसलिए मैं यहां पोस्ट पुन: प्रस्तुत कर रहा हूं


WPF और सिल्वरलाइट दोनों ही "बेस्ड" प्रॉपर्टी के माध्यम से एक स्टाइल को दूसरी स्टाइल से प्राप्त करने की क्षमता प्रदान करते हैं। यह सुविधा डेवलपर्स को अपनी विरासत को वर्ग विरासत के समान एक पदानुक्रम का उपयोग करके व्यवस्थित करने में सक्षम बनाती है। निम्नलिखित शैलियों पर विचार करें:

<Style TargetType="Button" x:Key="BaseButtonStyle">
    <Setter Property="Margin" Value="10" />
</Style>
<Style TargetType="Button" x:Key="RedButtonStyle" BasedOn="{StaticResource BaseButtonStyle}">
    <Setter Property="Foreground" Value="Red" />
</Style>

इस सिंटैक्स के साथ, एक बटन जो RedButtonStyle का उपयोग करता है, उसकी अग्रभूमि संपत्ति रेड में सेट होगी और इसकी मार्जिन संपत्ति 10 पर सेट होगी।

यह सुविधा लंबे समय से WPF में है, और यह सिल्वरलाइट 3 में नया है।

यदि आप किसी तत्व पर एक से अधिक शैली सेट करना चाहते हैं तो क्या होगा? इस समस्या के समाधान के लिए न तो WPF और न ही सिल्वरलाइट प्रदान करता है। सौभाग्य से WPF में इस व्यवहार को लागू करने के तरीके हैं, जिनके बारे में मैं इस ब्लॉग पोस्ट में चर्चा करूंगा।

WPF और सिल्वरलाइट मार्कअप एक्सटेंशन का उपयोग उन मूल्यों के साथ प्रदान करने के लिए करते हैं जिन्हें प्राप्त करने के लिए कुछ तर्क की आवश्यकता होती है। XAML में उनके आसपास घुंघराले कोष्ठक की उपस्थिति से मार्कअप एक्सटेंशन आसानी से पहचाने जा सकते हैं। उदाहरण के लिए, {बाइंडिंग} मार्कअप एक्सटेंशन में डेटा स्रोत से मान प्राप्त करने और परिवर्तन होने पर इसे अपडेट करने के लिए तर्क होते हैं; {StaticResource} मार्कअप एक्सटेंशन में कुंजी के आधार पर संसाधन शब्दकोश से मान हथियाने के लिए तर्क सम्‍मिलित हैं। सौभाग्य से, हमारे लिए, WPF उपयोगकर्ताओं को अपने स्वयं के कस्टम मार्कअप एक्सटेंशन लिखने की अनुमति देता है। यह विशेषता अभी तक सिल्वरलाइट में मौजूद नहीं है, इसलिए इस ब्लॉग में समाधान केवल WPF पर लागू है।

दूसरों ने मार्कअप एक्सटेंशन का उपयोग करके दो शैलियों को मर्ज करने के लिए महान समाधान लिखे हैं। हालांकि, मैं एक ऐसा समाधान चाहता था जो असीमित संख्या में शैलियों को मर्ज करने की क्षमता प्रदान करता हो, जो थोड़ा सा पेचीदा है।

मार्कअप एक्सटेंशन लिखना सीधा है। पहला चरण एक ऐसी क्लास बनाना है जो मार्कअपएक्स्टेंशन से निकलती है, और यह इंगित करने के लिए मार्कअपएक्स्टेंशन रीटर्नटाइप विशेषता का उपयोग करें कि आप अपने मार्कअप एक्सटेंशन से लौटाए गए मान को टाइप स्टाइल का होना चाहते हैं।

[MarkupExtensionReturnType(typeof(Style))]
public class MultiStyleExtension : MarkupExtension
{
}

मार्कअप एक्सटेंशन में इनपुट निर्दिष्ट करना

हम अपने मार्कअप एक्सटेंशन के उपयोगकर्ताओं को मर्ज करने के लिए शैलियों को निर्दिष्ट करने का एक सरल तरीका देना चाहते हैं। अनिवार्य रूप से दो तरीके हैं जिसमें उपयोगकर्ता एक मार्कअप एक्सटेंशन के लिए इनपुट निर्दिष्ट कर सकता है। उपयोगकर्ता गुण सेट कर सकता है या निर्माणकर्ता को पैरामीटर पास कर सकता है। चूंकि इस परिदृश्य में उपयोगकर्ता को असीमित संख्या में शैलियों को निर्दिष्ट करने की क्षमता की आवश्यकता होती है, मेरा पहला दृष्टिकोण एक ऐसा निर्माता बनाना था जो "परमेस" कीवर्ड का उपयोग करके किसी भी संख्या में तार लेता है:

public MultiStyleExtension(params string[] inputResourceKeys)
{
}

मेरा लक्ष्य निम्नानुसार इनपुट लिखने में सक्षम होना था:

<Button Style="{local:MultiStyle BigButtonStyle, GreenButtonStyle}"  />

कॉमा को अलग-अलग स्टाइल की को अलग करते हुए नोटिस करें। दुर्भाग्य से, कस्टम मार्कअप एक्सटेंशन असीमित पैरामीटरों का समर्थन नहीं करते हैं, इसलिए यह दृष्टिकोण एक संकलन त्रुटि का परिणाम देता है। यदि मुझे पहले से पता था कि मैं कितने शैलियों का विलय करना चाहता हूं, तो मैं एक एक्सएएमएल सिंटैक्स का उपयोग कर सकता था, जिसमें एक कंस्ट्रक्टर वांछित संख्या ले सकता है:

public MultiStyleExtension(string inputResourceKey1, string inputResourceKey2)
{
}

वर्कअराउंड के रूप में, मैंने तय किया कि कंस्ट्रक्टर पैरामीटर को एक सिंगल स्ट्रिंग लें जो स्पेस द्वारा अलग किए गए स्टाइल नामों को निर्दिष्ट करता है। वाक्य-विन्यास बहुत बुरा नहीं है:

private string[] resourceKeys;

public MultiStyleExtension(string inputResourceKeys)
{
    if (inputResourceKeys == null)
    {
        throw new ArgumentNullException("inputResourceKeys");
    }

    this.resourceKeys = inputResourceKeys.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

    if (this.resourceKeys.Length == 0)
    {
        throw new ArgumentException("No input resource keys specified.");
    }
}

मार्कअप विस्तार के उत्पादन में गिना जा रहा है

एक मार्कअप एक्सटेंशन के आउटपुट की गणना करने के लिए, हमें "ProvValue" नामक मार्कअपटेक्स्टेंशन से एक विधि को ओवरराइड करना होगा। इस पद्धति से लौटाया गया मान मार्कअप एक्सटेंशन के लक्ष्य में सेट किया जाएगा।

मैंने स्टाइल के लिए एक विस्तार विधि बनाकर शुरुआत की जो दो शैलियों को मर्ज करना जानता है। इस विधि का कोड काफी सरल है:

public static void Merge(this Style style1, Style style2)
{
    if (style1 == null)
    {
        throw new ArgumentNullException("style1");
    }
    if (style2 == null)
    {
        throw new ArgumentNullException("style2");
    }

    if (style1.TargetType.IsAssignableFrom(style2.TargetType))
    {
        style1.TargetType = style2.TargetType;
    }

    if (style2.BasedOn != null)
    {
        Merge(style1, style2.BasedOn);
    }

    foreach (SetterBase currentSetter in style2.Setters)
    {
        style1.Setters.Add(currentSetter);
    }

    foreach (TriggerBase currentTrigger in style2.Triggers)
    {
        style1.Triggers.Add(currentTrigger);
    }

    // This code is only needed when using DynamicResources.
    foreach (object key in style2.Resources.Keys)
    {
        style1.Resources[key] = style2.Resources[key];
    }
}

ऊपर दिए गए तर्क के साथ, पहली शैली को दूसरी से सभी जानकारी शामिल करने के लिए संशोधित किया गया है। यदि विरोध होता है (जैसे दोनों शैलियों में एक ही संपत्ति के लिए एक सेटर है), दूसरी शैली जीतती है। ध्यान दें कि शैलियों और ट्रिगर्स को कॉपी करने से अलग, मैंने टारगेटप्राइप और बेस्डऑन मूल्यों के साथ-साथ किसी भी संसाधन को दूसरी शैली में भी ध्यान में रखा। मर्ज किए गए शैली के टारगेट टाइप के लिए, मैंने जो भी प्रकार का उपयोग किया है वह अधिक व्युत्पन्न है। यदि दूसरी शैली में एक आधार शैली है, तो मैं शैलियों की अपनी पदानुक्रम को पुन: विलय कर देता हूं। यदि इसके पास संसाधन हैं, तो मैं उन्हें पहली शैली में कॉपी करता हूं। यदि उन संसाधनों को {StaticResource} का उपयोग करने के लिए संदर्भित किया जाता है, तो वे इस मर्ज कोड को निष्पादित करने से पहले सांख्यिकीय रूप से हल हो जाते हैं, और इसलिए उन्हें स्थानांतरित करना आवश्यक नहीं है। मैंने इस कोड को उस स्थिति में जोड़ा है जब हम डायनामिक स्रोत का उपयोग कर रहे हैं।

ऊपर दिखाए गए विस्तार विधि निम्न सिंटैक्स सक्षम बनाता है:

style1.Merge(style2);

यह सिंटैक्स उपयोगी है बशर्ते कि मेरे पास ProvValue के भीतर दोनों शैलियों के उदाहरण हों। खैर, मैं नहीं। कंस्ट्रक्टर से मिलने वाली सभी स्टाइल्स की एक सूची है। अगर कोई निर्माता मानकों में पैरामीटर के लिए समर्थन था, मैं वास्तविक शैली उदाहरणों प्राप्त करने के लिए निम्नलिखित वाक्य रचना के लिए इस्तेमाल किया जा सकता था:

<Button Style="{local:MultiStyle {StaticResource BigButtonStyle}, {StaticResource GreenButtonStyle}}"/>
public MultiStyleExtension(params Style[] styles)
{
}

लेकिन वह काम नहीं करता है। और यहां तक ​​कि अगर परमेस लिमिटेशन मौजूद नहीं था, तो हम शायद मार्कअप एक्सटेंशन की एक और सीमा को मार देंगे, जहां हमें स्थैतिक संसाधनों को निर्दिष्ट करने के लिए विशेषता सिंटैक्स के बजाय गुण-तत्व सिंटैक्स का उपयोग करना होगा, जो क्रिया और बोझिल है (मैं इसे समझाता हूं) पिछले ब्लॉग पोस्ट में बग बेहतर )। और अगर उन दोनों सीमाओं का अस्तित्व नहीं था, तब भी मैं सिर्फ उनके नाम का उपयोग करते हुए शैलियों की सूची लिखूंगा - यह हर एक के लिए एक स्टेटिक स्रोत से पढ़ने के लिए कम और सरल है।

समाधान कोड का उपयोग करके एक StaticResourceExtension बनाने के लिए है। टाइप स्ट्रिंग और एक सेवा प्रदाता की शैली कुंजी को देखते हुए, मैं वास्तविक शैली के उदाहरण को पुनः प्राप्त करने के लिए StaticResourceExtension का उपयोग कर सकता हूं। यहाँ वाक्य रचना है:

Style currentStyle = new StaticResourceExtension(currentResourceKey).ProvideValue(serviceProvider) as Style;

अब हमारे पास ProvValue विधि लिखने के लिए आवश्यक सभी टुकड़े हैं:

public override object ProvideValue(IServiceProvider serviceProvider)
{
    Style resultStyle = new Style();

    foreach (string currentResourceKey in resourceKeys)
    {
        Style currentStyle = new StaticResourceExtension(currentResourceKey).ProvideValue(serviceProvider) as Style;

        if (currentStyle == null)
        {
            throw new InvalidOperationException("Could not find style with resource key " + currentResourceKey + ".");
        }

        resultStyle.Merge(currentStyle);
    }
    return resultStyle;
}

यहाँ MultiStyle मार्कअप एक्सटेंशन के उपयोग का एक पूरा उदाहरण है:

<Window.Resources>
    <Style TargetType="Button" x:Key="SmallButtonStyle">
        <Setter Property="Width" Value="120" />
        <Setter Property="Height" Value="25" />
        <Setter Property="FontSize" Value="12" />
    </Style>

    <Style TargetType="Button" x:Key="GreenButtonStyle">
        <Setter Property="Foreground" Value="Green" />
    </Style>

    <Style TargetType="Button" x:Key="BoldButtonStyle">
        <Setter Property="FontWeight" Value="Bold" />
    </Style>
</Window.Resources>

<Button Style="{local:MultiStyle SmallButtonStyle GreenButtonStyle BoldButtonStyle}" Content="Small, green, bold" />

यहाँ छवि विवरण दर्ज करें


3
वास्तव में अच्छा समाधान, लेकिन मुझे समझ में नहीं आता कि 3 या + शैली को मर्ज करने का कोई सरल उपाय क्यों नहीं है।
श्री Rubix

31

लेकिन आप दूसरे से विस्तार कर सकते हैं .. आधार संपत्ति पर एक नज़र डालें

<Style TargetType="TextBlock">
      <Setter Property="Margin" Value="3" />
</Style>

<Style x:Key="AlwaysVerticalStyle" TargetType="TextBlock" 
       BasedOn="{StaticResource {x:Type TextBlock}}">
     <Setter Property="VerticalAlignment" Value="Top" />
</Style>

यह मेरे लिए पर्याप्त था। tnks!
डेविड ले

लेकिन यह केवल तभी काम करता है जब दोनों शैलियाँ एक ही प्रकार की हों (XAML त्रुटि: "केवल एक शैली को लक्ष्य प्रकार के साथ आधार बना सकते हैं जो आधार प्रकार '<प्रकार>' है)
क्रिज़्सटॉफ़ बोशुरको

17

WPF / XAML इस कार्यक्षमता को मूल रूप से प्रदान नहीं करता है, लेकिन यह आपको जो आप चाहते हैं वह करने की अनुमति देने की व्यापकता प्रदान करता है।

हम एक ही ज़रूरत में भागे, और अपना खुद का XAML मार्कअप एक्सटेंशन (जिसे हमने "MergedStylesExtension" कहा जाता है) बनाने के लिए हमें दो अन्य शैलियों से एक नई शैली बनाने की अनुमति दी (जो कि, यदि आवश्यक हो, तो शायद एक बार में उपयोग किया जा सकता है) और भी अधिक शैलियों से विरासत की पंक्ति)।

WPF / XAML बग के कारण, हमें इसका उपयोग करने के लिए संपत्ति तत्व सिंटैक्स का उपयोग करने की आवश्यकता है, लेकिन इसके अलावा यह ठीक काम करने लगता है। उदाहरण के लिए,

<Button
    Content="This is an example of a button using two merged styles">
    <Button.Style>
      <ext:MergedStyles
                BasedOn="{StaticResource FirstStyle}"
                MergeStyle="{StaticResource SecondStyle}"/>
   </Button.Style>
</Button>

मैंने हाल ही में इसके बारे में यहाँ लिखा है: http://swdeveloper.wordpress.com/2009/01/03/wpf-xaml-multiple-style-inheritance-and-markup-extensions/


3

यह आपकी शैली का उपयोग करने और लपेटने के लिए एक सहायक वर्ग बनाकर संभव है। यहां उल्लेखित कंपाउंडसेल्टी दिखाता है कि यह कैसे करना है। कई तरीके हैं, लेकिन सबसे आसान निम्नलिखित करना है:

<TextBlock Text="Test"
    local:CompoundStyle.StyleKeys="headerStyle,textForMessageStyle,centeredStyle"/>

उम्मीद है की वो मदद करदे।


2

AttachedPropertyनिम्नलिखित कोड जैसी कई शैलियों को सेट करने के लिए उपयोग करें :

public class Css
{

    public static string GetClass(DependencyObject element)
    {
        if (element == null)
            throw new ArgumentNullException("element");

        return (string)element.GetValue(ClassProperty);
    }

    public static void SetClass(DependencyObject element, string value)
    {
        if (element == null)
            throw new ArgumentNullException("element");

        element.SetValue(ClassProperty, value);
    }


    public static readonly DependencyProperty ClassProperty =
        DependencyProperty.RegisterAttached("Class", typeof(string), typeof(Css), 
            new PropertyMetadata(null, OnClassChanged));

    private static void OnClassChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var ui = d as FrameworkElement;
        Style newStyle = new Style();

        if (e.NewValue != null)
        {
            var names = e.NewValue as string;
            var arr = names.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var name in arr)
            {
                Style style = ui.FindResource(name) as Style;
                foreach (var setter in style.Setters)
                {
                    newStyle.Setters.Add(setter);
                }
                foreach (var trigger in style.Triggers)
                {
                    newStyle.Triggers.Add(trigger);
                }
            }
        }
        ui.Style = newStyle;
    }
}

Usege:

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:style_a_class_like_css"
        mc:Ignorable="d"
        Title="MainWindow" Height="150" Width="325">
    <Window.Resources>

        <Style TargetType="TextBlock" x:Key="Red" >
            <Setter Property="Foreground" Value="Red"/>
        </Style>

        <Style TargetType="TextBlock" x:Key="Green" >
            <Setter Property="Foreground" Value="Green"/>
        </Style>

        <Style TargetType="TextBlock" x:Key="Size18" >
            <Setter Property="FontSize" Value="18"/>
            <Setter Property="Margin" Value="6"/>
        </Style>

        <Style TargetType="TextBlock" x:Key="Bold" >
            <Setter Property="FontWeight" Value="Bold"/>
        </Style>

    </Window.Resources>
    <StackPanel>

        <Button Content="Button" local:Css.Class="Red Bold" Width="75"/>
        <Button Content="Button" local:Css.Class="Red Size18" Width="75"/>
        <Button Content="Button" local:Css.Class="Green Size18 Bold" Width="75"/>

    </StackPanel>
</Window>

परिणाम:

यहाँ छवि विवरण दर्ज करें


1

यदि आप किसी विशिष्ट गुण को नहीं छू रहे हैं, तो आप शैली को सभी आधार और सामान्य गुण प्राप्त कर सकते हैं, जो लक्ष्य प्रकार फ्रेमवर्क होगा। फिर, आप उन सभी लक्षित गुणों के लिए विशिष्ट स्वाद बना सकते हैं, जिन्हें उन सभी सामान्य गुणों को फिर से कॉपी करने की आवश्यकता नहीं है।


1

आप शायद ऐसा ही कुछ प्राप्त कर सकते हैं यदि इसे स्टाइलसलेक्टर के उपयोग द्वारा वस्तुओं के संग्रह में लागू किया जाता है, तो मैंने इसका उपयोग पेड़ में बंधी वस्तु के प्रकार के आधार पर ट्रीविटाइम्स पर विभिन्न शैलियों का उपयोग करने में इसी तरह की समस्या के लिए किया है। आपको अपने विशेष दृष्टिकोण को समायोजित करने के लिए नीचे की कक्षा को थोड़ा संशोधित करना पड़ सकता है लेकिन उम्मीद है कि यह आपको शुरू कर देगा

public class MyTreeStyleSelector : StyleSelector
{
    public Style DefaultStyle
    {
        get;
        set;
    }

    public Style NewStyle
    {
        get;
        set;
    }

    public override Style SelectStyle(object item, DependencyObject container)
    {
        ItemsControl ctrl = ItemsControl.ItemsControlFromItemContainer(container);

        //apply to only the first element in the container (new node)
        if (item == ctrl.Items[0])
        {
            return NewStyle;
        }
        else
        {
            //otherwise use the default style
            return DefaultStyle;
        }
    }
}

आप इसके बाद इसे लागू करें

 <TreeView>
     <TreeView.ItemContainerStyleSelector
         <myassembly: MyTreeStyleSelector DefaultStyle = "{StaticResource DefaultItemStyle}"
                                         NewStyle = "{StaticResource NewItemStyle}" />
     </TreeView.ItemContainerStyleSelector>
  </ TreeView>

1

कभी-कभी आप पैनलों को घोंसले द्वारा इस तक पहुंच सकते हैं। मान लें कि आपके पास एक शैली है जो फ़ोरग्राउंड को बदल देती है और एक और परिवर्तन होता है FontSize, आप बाद वाले को एक टेक्स्टब्लॉक पर लागू कर सकते हैं, और इसे एक ग्रिड में रख सकते हैं जो इसकी शैली पहली है। यह मदद कर सकता है और कुछ मामलों में सबसे आसान तरीका हो सकता है, हालांकि यह सभी समस्याओं को हल नहीं करेगा।


1

जब आप SelectStyle को ओवरराइड करते हैं, तो आप नीचे की तरह प्रतिबिंब के माध्यम से GroupBy संपत्ति प्राप्त कर सकते हैं:

    public override Style SelectStyle(object item, DependencyObject container)
    {

        PropertyInfo p = item.GetType().GetProperty("GroupBy", BindingFlags.NonPublic | BindingFlags.Instance);

        PropertyGroupDescription propertyGroupDescription = (PropertyGroupDescription)p.GetValue(item);

        if (propertyGroupDescription != null && propertyGroupDescription.PropertyName == "Title" )
        {
            return this.TitleStyle;
        }

        if (propertyGroupDescription != null && propertyGroupDescription.PropertyName == "Date")
        {
            return this.DateStyle;
        }

        return null;
    }

0

यदि आप आधार शैली के अतिरिक्त केवल एक ही तत्व के लिए एक अनूठी शैली लागू करने का प्रयास कर रहे हैं , तो ऐसा करने के लिए एक पूरी तरह से अलग तरीका है जो पठनीय और बनाए रखने योग्य कोड के लिए IMHO बेहतर है।

व्यक्तिगत तत्व के प्रति मापदंडों को ट्विक करना बेहद आम है। केवल एक तत्व पर उपयोग के लिए शब्दकोश शैलियों को परिभाषित करना बनाए रखने या समझने के लिए बेहद बोझिल है। केवल एक-ऑफ एलिमेंट ट्वीक्स के लिए स्टाइल बनाने से बचने के लिए, मेरे अपने प्रश्न का उत्तर यहां पढ़ें:

https://stackoverflow.com/a/54497665/1402498

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.