मेरे पास एक संपत्ति है जो डेटाबेस डेटा प्रकार है (char, DateTime, int, float आदि ...) और मैं उपयोग किए गए नियंत्रण को बदलना चाहता हूं चयनित प्रकार का मान दर्ज करें। तो पाठ मानों के लिए मुझे एक TextBox चाहिए और दिनांक मानों के लिए मुझे एक DatePicker चाहिए।

ऐसा करने का एक तरीका यह था कि मेरे फॉर्म पर प्रत्येक नियंत्रण में से एक हो और एक उपयुक्त IValueConverter कार्यान्वयन का उपयोग करके अपना Visibility सेट करें। मुझे पता है कि यह काम करेगा, लेकिन यह बहुत सारे कोड बनाएगा और बहुत अच्छा नहीं लगेगा।

दूसरा तरीका मैंने सोचा था कि एक ContentPresenter का उपयोग करें और इसकी सामग्री को Style और DataTriggers के साथ सेट करें, लेकिन मैं इसे काम पर नहीं ला सकता।

<Style x:Key="TypedValueHelper" TargetType="{x:Type ContentPresenter}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Char">
            <Setter Property="Content" Value="???"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Date">
            <Setter Property="Content" Value="???"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Integer">
            <Setter Property="Content" Value="???"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

अगर कोई मेरा "???" भर सकता है या कोई बेहतर समाधान सुझा सकता है तो कृपया करें।

14
Jon Mitchell 26 मई 2010, 13:27

3 जवाब

सबसे बढ़िया उत्तर

आप सेटर्स और डेटा टेम्पलेट्स के साथ स्टाइल का संयोजन कर सकते हैं। आपके पास मूल रूप से इसके लिए आपके कोड में शुरुआत है, हालांकि मुझे नहीं लगता कि ContentPresenter शैली का सही नियंत्रण है, क्योंकि इसमें कोई टेम्पलेट नहीं है।

इस तरह एक स्टाइल बनाएं:

<Style x:Key="TypedValueHelper" TargetType="{x:Type ContentControl}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Char">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <TextBox Text="{Binding Path=.}" />
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=DataType}" Value="Integer">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <Slider Maximum="100" Minimum="0" Value="{Binding Path=.}"
                                         Orientation="Horizontal" />
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>

फिर शैली का उपयोग ContentControl में करें:

<ContentControl Content="{Binding MyValue}"
                        Style="{StaticResource TypedValueHelper}">
13
Eitan Asayag 20 फरवरी 2020, 21:32
मुझे यकीन नहीं है कि मैं अपना कोड साझा कर सकता हूं क्योंकि बहुत सारी निर्भरताएं हैं। वास्तव में मेरी वास्तविक समस्या जितनी मैंने दी है उससे कहीं अधिक जटिल है। मुझे पूरा यकीन है कि आप समाधान मेरे लिए काम करेंगे मुझे अभी एक समस्या मिली है जहां मैं सामग्री नियंत्रण की सामग्री को {बाध्यकारी} के बजाय {बाध्यकारी} पर सेट करने का प्रयास कर रहा हूं जिसका अर्थ है कि डब्ल्यूपीएफ मेरे व्यूमोडेल के लिए दृश्य लोड करता है सामग्री नियंत्रण में, और पुनरावर्ती रूप से चलता रहता है ...
 – 
Jon Mitchell
26 मई 2010, 15:54
ओह समझा। क्या आपने {बाध्यकारी पथ =।} की कोशिश की?
 – 
ThomasAndersson
26 मई 2010, 16:11
क्रमबद्ध! मुझे के DateType को ViewModel के प्रकार पर सेट करना था। मुझे लगता है कि यह ViewModel प्रकार और उस दृश्य के बीच स्थानीय रूप से स्कोप्ड बाइंडिंग बनाता है जिसे मैं प्रदर्शित करना चाहता हूं। एक बार फिर धन्यवाद!!
 – 
Jon Mitchell
26 मई 2010, 17:32

जबकि Style समाधान काम कर सकता है, गतिशील सामग्री व्यवहार को लागू करने का उचित तरीका डेटा टेम्पलेट्स का उपयोग करना होगा जैसा कि Sdry ने सुझाव दिया था। हालांकि, आप यह निर्धारित करने के लिए एक गणना का उपयोग कर रहे होंगे कि कौन सा डेटा टेम्पलेट उपयोग करना है, जिसका अनिवार्य रूप से मतलब है कि आप एक ही प्रकार को एकाधिक डेटा टेम्पलेट्स में मैप करना चाहते हैं। यह समस्या DataTemplateSelector वर्ग द्वारा हल की गई है, निम्नलिखित विवरण सीधे MSDN से है:

"आमतौर पर, आप एक डेटा टेम्पलेट चयनकर्ता बनाते हैं जब आपके पास एक ही प्रकार की वस्तुओं के लिए एक से अधिक डेटा टेम्पलेट होते हैं और आप प्रत्येक डेटा ऑब्जेक्ट के गुणों के आधार पर लागू करने के लिए डेटा टेम्पलेट चुनने के लिए अपना तर्क प्रदान करना चाहते हैं।"

आपकी गतिशील सामग्री को इस तरह से एक ContentControl द्वारा होस्ट किया जाना चाहिए:

<ContentControl Content="{Binding Path=ReferenceToYourViewModel}" ContentTemplateSelector="{DynamicResource MyTemplateSelector}"/>

MyTemplateSelector का कार्यान्वयन:

public class MyTemplateSelector: DataTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        FrameworkElement elem = container as FrameworkElement;
        if(elem == null)
        {
            return null;
        }
        if (item == null || !(item is YourViewModel))
        {
            throw new ApplicationException();
        }
        if ((item as YourViewModel).DataType == DataType.Char)
        {
            return elem.FindResource("CharDataTemplate") as DataTemplate;
        }
        if ((item as YourViewModel).DataType == DataType.Date)
        {
            return elem.FindResource("DateDataTemplate") as DataTemplate;
        }
        if ((item as YourViewModel).DataType == DataType.Integer)
        {
            return elem.FindResource("IntegerDataTemplate") as DataTemplate;
        }
        throw new ApplicationException();
    }
}

फिर जैसा कि आप उम्मीद करेंगे, यहां से चुनने के लिए डेटा टेम्पलेट हैं:

<DataTemplate x:Key="CharDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate>
<DataTemplate x:Key="DateDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate>
<DataTemplate x:Key="IntegerDataTemplate" DataType="{x:Type YourViewModel}">Put Your Xaml Here</DataTemplate>

इसके साथ, आपके व्यू मॉडल की DataType प्रॉपर्टी के आधार पर उपयुक्त DataTemplate का चयन किया जाएगा। जो मेरी राय में Visibility या Styles.

11
Eitan Asayag 20 फरवरी 2020, 20:30

मैं डेटा टेम्पलेट्स में देखूंगा। उदाहरण के लिए:

<DataTemplate DataType="{x:Type local:Input}">
    <local:InputControl DataContext="{Binding}" />
</DataTemplate>

<DataTemplate DataType="{x:Type data:VideoData}">
    <local:VideoControl DataContext="{Binding}"></local:VideoControl>
</DataTemplate>
0
Eitan Asayag 20 फरवरी 2020, 21:07
मुझे यकीन नहीं है कि यह मेरे लिए काम करेगा क्योंकि मैं अपनी पसंद का नियंत्रण बनाने के लिए वास्तविक 'प्रकार' का उपयोग नहीं कर रहा हूं, मैं अपने व्यूमोडेल पर एक संपत्ति के रूप में उजागर एक गणना मूल्य का उपयोग कर रहा हूं।
 – 
Jon Mitchell
26 मई 2010, 14:04