কীভাবে NAMED বিষয়বস্তু দিয়ে একটি ডাব্লুপিএফ ব্যবহারকারীকন্ট্রোল তৈরি করবেন


102

আমার সংযুক্ত কমান্ড এবং যুক্তিযুক্ত নিয়ন্ত্রণ রয়েছে যা নিয়মিতভাবে একইভাবে পুনরায় ব্যবহার করা হয় used আমি এমন একটি ব্যবহারকারী নিয়ন্ত্রণ তৈরি করার সিদ্ধান্ত নিয়েছি যা সমস্ত সাধারণ নিয়ন্ত্রণ এবং যুক্তি ধারণ করে।

তবে নামকরণ করা যায় এমন সামগ্রী রাখতে সক্ষম হওয়ার জন্য আমার নিয়ন্ত্রণও দরকার। আমি নিম্নলিখিত চেষ্টা করেছিলাম:

<UserControl.ContentTemplate>
    <DataTemplate>
        <Button>a reused button</Button>
        <ContentPresenter Content="{TemplateBinding Content}"/>
        <Button>a reused button</Button>
    </DataTemplate>
</UserControl.ContentTemplate>

তবে এটি মনে হয় যে ব্যবহারকারীর নিয়ন্ত্রণের ভিতরে থাকা কোনও সামগ্রীর নাম দেওয়া যায় না। উদাহরণস্বরূপ যদি আমি নিয়ন্ত্রণটি নিম্নলিখিত উপায়ে ব্যবহার করি:

<lib:UserControl1>
     <Button Name="buttonName">content</Button>
</lib:UserControl1>

আমি নিম্নলিখিত ত্রুটিটি পেয়েছি:

এলিমেন্ট 'বোতামে' বোতামনাম 'নামের বৈশিষ্ট্য মান সেট করতে পারে না। 'বাটন' উপাদান 'ব্যবহারকারীকন্ট্রোল 1' এর আওতায় রয়েছে, এটি ইতিমধ্যে একটি নাম নিবন্ধীকৃত ছিল যখন এটি অন্য স্কোপে সংজ্ঞায়িত করা হয়েছিল।

আমি যদি বোতামের নামটি সরিয়ে ফেলি, তবে এটি সংকলন করে তবে কন্টেন্টটির নাম রাখতে আমার সক্ষম হওয়া দরকার। আমি কীভাবে এটি অর্জন করতে পারি?


এটি একটি কাকতালীয় ঘটনা। আমি এই প্রশ্নটি করতেই চলেছিলাম! আমি একই সমস্যা আছে। ইউজারকন্ট্রোলের মধ্যে সাধারণ ইউআই প্যাটার্নটি তৈরি করে তবে নামটি দিয়ে UI বিষয়বস্তু উল্লেখ করতে চায়।
ম্যাকেনির

4
এই লোকটি তার কাস্টম নিয়ন্ত্রণের এক্সএএমএল ফাইলটি থেকে মুক্তি পেয়ে এবং কাস্টম নিয়ন্ত্রণের ইউআই প্রোগ্রামক্রমে তৈরির সাথে জড়িত একটি সমাধান খুঁজে পেয়েছে । এই ব্লগ পোস্টটি বিষয় সম্পর্কে আরও বলতে হবে।
ম্যাকেনির

4
আপনি কেন রিসোর্সডোডেরিশ ব্যবহার করবেন না? এটিতে ডেটােম্প্লেট সংজ্ঞায়িত করুন। বা নিয়ন্ত্রণটি উত্তরাধিকারী করার জন্য ভিত্তিভুক্ত কীওয়ার্ডটি ব্যবহার করুন। ডাব্লুপিএফ-তে ইউ-আই-কোড করার আগে আমি কয়েকটি পথ অনুসরণ করেছি ...
লুই কোটম্যান

উত্তর:


46

উত্তরটি হ'ল এটি করতে কোনও ইউজারকন্ট্রোল ব্যবহার না করা।

এমন একটি শ্রেণি তৈরি করুন যা কন্টেন্টকন্ট্রোলকে প্রসারিত করবে

public class MyFunkyControl : ContentControl
{
    public static readonly DependencyProperty HeadingProperty =
        DependencyProperty.Register("Heading", typeof(string),
        typeof(HeadingContainer), new PropertyMetadata(HeadingChanged));

    private static void HeadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((HeadingContainer) d).Heading = e.NewValue as string;
    }

    public string Heading { get; set; }
}

তারপরে সামগ্রীগুলি নির্দিষ্ট করতে একটি শৈলী ব্যবহার করুন

<Style TargetType="control:MyFunkyControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="control:MyFunkyContainer">
                <Grid>
                    <ContentControl Content="{TemplateBinding Content}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

এবং অবশেষে - এটি ব্যবহার করুন

<control:MyFunkyControl Heading="Some heading!">            
    <Label Name="WithAName">Some cool content</Label>
</control:MyFunkyControl>

4
আমি এটি আসলে সবচেয়ে আরামদায়ক সমাধানের মধ্যে পেয়েছি যেহেতু আপনি ডিজাইনার ব্যবহার করে কোনও সাধারণ ব্যবহারকারীকন্ট্রোলটিতে কন্ট্রোলটেম্পলেটটি বের করতে পারেন এবং এটি এটিকে সম্পর্কিত কন্ট্রোল টেমপ্লেটের সাথে একটি স্টাইলে রূপান্তরিত করতে পারে।
অলিভার ওয়েচোল্ড

4
হুম, এটি আপনার জন্য কিছুটা অদ্ভুত কাজ করে, কারণ আমি এই পদ্ধতির প্রয়োগ করার চেষ্টা করেছি এবং আমার ক্ষেত্রে আমি এখনও এই কুখ্যাত ত্রুটি পেয়েছি।
গ্রিনোল্ডম্যান

8
@ গ্রীনল্ডম্যান @ ব্যাডবয় আমার মনে হয় আমি জানি কেন এটি আপনার পক্ষে কাজ করে নি। আপনি সম্ভবত UserControlউত্তরাধিকার হিসাবে একটি বিদ্যমান কোড পরিবর্তন করেছেন ContentControl। সমাধানের জন্য, কেবল নতুন ক্লাস যুক্ত করুন ( সিএস সহ এক্সএএমএল নয় )। এবং তারপরে এটি (আশাবাদী) কাজ করবে। যদি আপনি চান, আমি একটি ছোট ভিএস 2010 সমাধান
এটি

4
বহু বছর পরে এবং আমি আশা করি আমি আবার এটিকে উত্সাহিত করতে পারব :)
ড্রয় নোকস

4
আমি অনুমান করি HeadingContainerএবং MyFunkyContainerবোঝাতে চাইছি MyFunkyControl?!
মার্টিন স্নাইডার

20

এক্সএএমএল ব্যবহৃত হয় তখন এটি সম্ভব হয় না বলে মনে হয়। কাস্টম নিয়ন্ত্রণগুলি যখন আমার কাছে আমার সমস্ত কন্ট্রোল থাকে তখন কাস্টম নিয়ন্ত্রণগুলি ওভারকিল বলে মনে হয়, তবে কেবলমাত্র একটি সামান্য যুক্তি দিয়ে তাদেরকে গ্রুপবদ্ধ করা এবং নামযুক্ত সামগ্রীকে অনুমতি দেওয়া দরকার।

জ্যাকির ব্লগে ম্যাকেনিয়ার হিসাবে সমাধানটি সমাধান হিসাবে বোঝা যাচ্ছে যে সবচেয়ে ভাল আপস হয়েছে। এক্সএএমএলগুলিতে নিয়ন্ত্রণগুলি এখনও সংজ্ঞায়িত করার অনুমতি দেওয়ার জন্য জেডিটির সমাধানটি বাড়ানোর উপায় হতে পারে:

    protected override void OnInitialized(EventArgs e)
    {
        base.OnInitialized(e);

        var grid = new Grid();
        var content = new ContentPresenter
                          {
                              Content = Content
                          };

        var userControl = new UserControlDefinedInXAML();
        userControl.aStackPanel.Children.Add(content);

        grid.Children.Add(userControl);
        Content = grid;           
    }

উপরের আমার উদাহরণে আমি ইউজারকন্ট্রোলডিফাইনডআইএনএক্সএএমএল নামে একটি ব্যবহারকারী নিয়ন্ত্রণ তৈরি করেছি যা এক্সএএমএল ব্যবহার করে কোনও সাধারণ ব্যবহারকারী নিয়ন্ত্রণের মতো সংজ্ঞায়িত হয়। আমার ইউজারকন্ট্রোলডিফাইনডআইএনএক্সএএমএল-তে আমার কাছে স্ট্যাকপ্যানেল নামে একটি স্ট্যাকপ্যানেল রয়েছে যার মধ্যে আমি চাইছি যে আমার নামযুক্ত সামগ্রীটি প্রদর্শিত হোক।


আমি খুঁজে পেয়েছি যে সামগ্রীটি পুনরায় প্যারেন্টিংয়ের এই প্রক্রিয়াটি ব্যবহার করার সময় আমি ডেটা বাইন্ডিং সমস্যা পেয়েছি। ডেটা বাইন্ডিং সঠিকভাবে সেট আপ হয়েছে বলে মনে হয়, তবে ডেটা উত্স থেকে নিয়ন্ত্রণগুলির প্রাথমিক পপুলেটিং সঠিকভাবে কাজ করে না। আমি মনে করি সমস্যাগুলি এমন নিয়ন্ত্রণগুলিতে সীমাবদ্ধ যা সামগ্রী উপস্থাপকের সরাসরি শিশু নয়।
ম্যাকেনির

এর পর থেকে এটি নিয়ে পরীক্ষার সুযোগ হয়নি, তবে ইউজারকন্ট্রোলডিফাইনডআইএনএক্সএএমএল (উপরের উদাহরণ থেকে) বা এ পর্যন্ত কনটেন্টপ্রেসেন্টারে যুক্ত হওয়া নিয়ন্ত্রণগুলিতে ডেটাবাইন্ডিংয়ের ক্ষেত্রে আমার কোনও সমস্যা হয়নি। আমি কোডের মাধ্যমে কেবল ডেটাবাইন্ডিং করে যাচ্ছি (এক্সএএমএল নয় - এটি কোনও পার্থক্য করে কিনা তা নিশ্চিত নন)।
রায়ান 16

দেখে মনে হচ্ছে এটি কোনও পার্থক্য করে। আপনার বর্ণিত ক্ষেত্রে আমি কেবলমাত্র ডেটা বাইন্ডিংয়ের জন্য এক্সএএমএল ব্যবহার করার চেষ্টা করেছি এবং এটি কার্যকর হয় না। তবে আমি কোডে সেট করে দিলে এটি কাজ করে!
রায়ান

3

আরেকটি বিকল্প আমি ব্যবহার করেছি হ'ল ইভেন্টটিতে Nameসম্পত্তি সেট করা Loaded

আমার ক্ষেত্রে আমার একটি জটিল জটিল নিয়ন্ত্রণ ছিল যা আমি কোড-পেছনে তৈরি করতে চাইনি এবং এটি নির্দিষ্ট আচরণের জন্য একটি নির্দিষ্ট নাম সহ একটি alচ্ছিক নিয়ন্ত্রণের সন্ধান করেছিল এবং যেহেতু আমি লক্ষ্য করেছি যে আমি নামটি একটিতে সেট করতে পারি DataTemplateআমি অনুভূত আমি Loadedইভেন্টে এটি করতে পারে ।

private void Button_Loaded(object sender, RoutedEventArgs e)
{
    Button b = sender as Button;
    b.Name = "buttonName";
}

4
আপনি যদি এটি করেন, তবে নামটি ব্যবহার করে বাইন্ডিংগুলি কাজ করবে না ... যদি না আপনি পেছনের কোডটিতে বাইন্ডিং সেট করেন।
টাওয়ার

3

কখনও কখনও আপনার কেবল সি # থেকে উপাদানটি উল্লেখ করতে পারে। ব্যবহারের ক্ষেত্রে উপর নির্ভর করে আপনি তার x:Uidপরিবর্তে একটি সেট সেট করতে পারেন x:Nameএবং ডাব্লুপিএফ-তে তার ইউআইডি দ্বারা আইটেম গেটের মতো একটি ইউআইডি সন্ধানকারী পদ্ধতি কল করে উপাদানগুলির অ্যাক্সেস করতে পারেন ।


1

আপনি ব্যবহারকারীর নিয়ন্ত্রণের মধ্যে সেট নামের জন্য এই সহায়কটি ব্যবহার করতে পারেন:

using System;
using System.Reflection;
using System.Windows;
using System.Windows.Media;
namespace UI.Helpers
{
    public class UserControlNameHelper
    {
        public static string GetName(DependencyObject d)
        {
            return (string)d.GetValue(UserControlNameHelper.NameProperty);
        }

        public static void SetName(DependencyObject d, string val)
        {
            d.SetValue(UserControlNameHelper.NameProperty, val);
        }

        public static readonly DependencyProperty NameProperty =
            DependencyProperty.RegisterAttached("Name",
                typeof(string),
                typeof(UserControlNameHelper),
                new FrameworkPropertyMetadata("",
                    FrameworkPropertyMetadataOptions.None,
                    (d, e) =>
                    {
                        if (!string.IsNullOrEmpty((string)e.NewValue))
                        {
                            string[] names = e.NewValue.ToString().Split(new char[] { ',' });

                            if (d is FrameworkElement)
                            {
                                ((FrameworkElement)d).Name = names[0];
                                Type t = Type.GetType(names[1]);
                                if (t == null)
                                    return;
                                var parent = FindVisualParent(d, t);
                                if (parent == null)
                                    return;
                                var p = parent.GetType().GetProperty(names[0], BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty);
                                p.SetValue(parent, d, null);
                            }
                        }
                    }));

        public static DependencyObject FindVisualParent(DependencyObject child, Type t)
        {
            // get parent item
            DependencyObject parentObject = VisualTreeHelper.GetParent(child);

            // we’ve reached the end of the tree
            if (parentObject == null)
            {
                var p = ((FrameworkElement)child).Parent;
                if (p == null)
                    return null;
                parentObject = p;
            }

            // check if the parent matches the type we’re looking for
            DependencyObject parent = parentObject.GetType() == t ? parentObject : null;
            if (parent != null)
            {
                return parent;
            }
            else
            {
                // use recursion to proceed with next level
                return FindVisualParent(parentObject, t);
            }
        }
    }
}

এবং আপনার উইন্ডো বা নিয়ন্ত্রণ কোডের পিছনে আপনাকে সম্পত্তি দ্বারা নিয়ন্ত্রণ সেট করে:

 public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

    }

    public Button BtnOK { get; set; }
}

আপনার উইন্ডো xaml:

    <Window x:Class="user_Control_Name.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:test="clr-namespace:user_Control_Name"
            xmlns:helper="clr-namespace:UI.Helpers" x:Name="mainWindow"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <test:TestUserControl>
                <Button helper:UserControlNameHelper.Name="BtnOK,user_Control_Name.MainWindow"/>
            </test:TestUserControl>
            <TextBlock Text="{Binding ElementName=mainWindow,Path=BtnOK.Name}"/>
        </Grid>
    </Window>

ইউজারকন্ট্রোলনামহেল্পার আপনার সম্পত্তি নিয়ন্ত্রণ এবং সম্পত্তিতে সেট করার জন্য শ্রেণীর নাম পান।


0

আমার প্রয়োজন প্রতিটি উপাদানগুলির জন্য একটি অতিরিক্ত সম্পত্তি তৈরি করতে আমি বেছে নিয়েছি:

    public FrameworkElement First
    {
        get
        {
            if (Controls.Count > 0)
            {
                return Controls[0];
            }
            return null;
        }
    }

এটি আমাকে এক্সএএমএল-এ শিশু উপাদানগুলিতে অ্যাক্সেস করতে সক্ষম করে:

<TextBlock Text="{Binding First.SelectedItem, ElementName=Taxcode}"/>

0
<Popup>
    <TextBox Loaded="BlahTextBox_Loaded" />
</Popup>

পিছনে কোড:

public TextBox BlahTextBox { get; set; }
private void BlahTextBox_Loaded(object sender, RoutedEventArgs e)
{
    BlahTextBox = sender as TextBox;
}

মাইক্রোসফ্টের আসল সমাধান হ'ল মাইক্রোসফ্ট এই সমস্যাটি ঠিক করার পাশাপাশি সেইসাথে ভাঙা ভিজ্যুয়াল গাছ ইত্যাদিসহ অন্য সকলকে হাইপোথিটিক্যালি বলছে।


0

তবুও আরেকটি কর্মসূচী: উপাদানটি সম্পর্কিত সম্পর্কিত উত্স হিসাবে উল্লেখ করুন ।


0

নামী নিয়ন্ত্রণগুলির একটি গুচ্ছ স্থাপন করার সময় আমার একটি ট্যাব নিয়ন্ত্রণকারী ব্যবহার করার সময় একই সমস্যা হয়েছিল।

আমার কর্মসংস্থানটি এমন একটি নিয়ন্ত্রণ টেম্পলেট ব্যবহার করা ছিল যা আমার সমস্ত কন্ট্রোলকে একটি ট্যাব পৃষ্ঠায় দেখানোর জন্য রয়েছে। টেমপ্লেটের অভ্যন্তরে আপনি নাম বৈশিষ্ট্যটি ব্যবহার করতে পারেন এবং কমপক্ষে একই টেমপ্লেটের অভ্যন্তরে অন্য নিয়ন্ত্রণগুলি থেকে নামকৃত নিয়ন্ত্রণের বৈশিষ্ট্যগুলিতে ডেটা বন্ডও রাখতে পারেন।

ট্যাব আইটেম নিয়ন্ত্রণের সামগ্রী হিসাবে, একটি সাধারণ নিয়ন্ত্রণ ব্যবহার করুন এবং সেই অনুযায়ী কন্ট্রোলটিপ্লেট সেট করুন:

<Control Template="{StaticResource MyControlTemplate}"/>

আপনার পিছনের কোড থেকে টেমপ্লেটের অভ্যন্তরে যাদের নামকরণ করা হয়েছে তাদের অ্যাক্সেস করার জন্য ভিজ্যুয়াল ট্রি ব্যবহার করা দরকার।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.