একটি কাস্টম তালিকায় একটি ডাব্লুপিএফ কম্বোবক্সকে বাঁধাই


186

আমার একটি কম্বোবক্স রয়েছে যা সিলেক্টডিজম / সিলেক্টভ্যালু আপডেট করার মতো মনে হচ্ছে না।

কম্বোবক্স আইটেমসোর্স ভিউমোডেল ক্লাসের এমন একটি সম্পত্তিতে আবদ্ধ যা একটি কালেকভিউ হিসাবে আরএএস ফোনবুক এন্ট্রিগুলির একটি গোছা তালিকাভুক্ত করে। তারপরে আমি ভিউমোডেলের অন্য সম্পত্তি SelectedItemবা পৃথক সময়ে উভয়কেই আবদ্ধ করেছি SelectedValue। আমি ডেটাবাইন্ডিং দ্বারা নির্ধারিত মানগুলি ডিবাগ করতে সেভ কমান্ডে একটি বার্তাবক্স যুক্ত করেছি, তবে SelectedItem/ SelectedValueবাইন্ডিং সেট করা হচ্ছে না।

ভিউমোডেল ক্লাসটি এরকম কিছু দেখায়:

public ConnectionViewModel
{
    private readonly CollectionView _phonebookEntries;
    private string _phonebookeEntry;

    public CollectionView PhonebookEntries
    {
        get { return _phonebookEntries; }
    }

    public string PhonebookEntry
    {
        get { return _phonebookEntry; }
        set
        {
            if (_phonebookEntry == value) return;
            _phonebookEntry = value;
            OnPropertyChanged("PhonebookEntry");
        }
    }
}

ব্যবসায়ের কোনও অবজেক্ট থেকে কনট্রাক্টরে _ফোনবুকএন্ট্রি সংগ্রহ শুরু করা হচ্ছে। কম্বোবক্স এক্সএএমএল দেখতে এমন কিছু দেখাচ্ছে:

<ComboBox ItemsSource="{Binding Path=PhonebookEntries}"
    DisplayMemberPath="Name"
    SelectedValuePath="Name"
    SelectedValue="{Binding Path=PhonebookEntry}" />

আমি কেবল কম্বোবক্সে প্রদর্শিত প্রকৃত স্ট্রিং মানটিতে আগ্রহী, বস্তুর অন্য কোনও বৈশিষ্ট্য নয় কারণ আমি ভিপিএন সংযোগ তৈরি করতে চাইলে আরএএস-এ যেতে হবে এমন মানটি, অতএব DisplayMemberPathএবং SelectedValuePathউভয়েরই নাম সম্পত্তি সংযোগভিউমোডেল। কম্বো একটি হল DataTemplateএকটি প্রয়োগ ItemsControlএকটি উইন্ডো যার DataContext একটি ViewModel উদাহরণস্বরূপ এ সেট করা হয়েছে হয়েছে।

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

কম্বোবক্সে ডেটাবাইন্ডিংয়ের সাথে আমি কী মিস করছি? আমি অনেক অনুসন্ধান করেছি এবং এমন কিছু খুঁজে পাচ্ছি না যা আমি ভুল করছি।


এটি এমন আচরণ যা আমি দেখছি, তবে এটি আমার নির্দিষ্ট প্রসঙ্গে কোনও কারণে কাজ করছে না।

আমার একটি মেইন উইন্ডোভিউমোডেল রয়েছে যার একটি সংযোগভিউমোডেল রয়েছে CollectionView। মেইন উইন্ডোভিউ.অ্যাক্স্যামেল ফাইল কোড-এর পিছনে, আমি ডেটা কনটেক্সটটি মেইনওয়াইন্ডভিউমোডেলে সেট করেছি। মেইন উইন্ডোভিউ.এক্সএএমএল এর সংযোগভিউমোডেল ItemsControlসংগ্রহের সীমাবদ্ধ। আমার কাছে একটি ডেটা টেম্পলেট রয়েছে যা কম্বোবক্স পাশাপাশি কিছু অন্যান্য টেক্সটবক্সও ধারণ করে। পাঠ্যবক্সগুলি সংযোগভিউমোডেল ব্যবহার করে সরাসরি বৈশিষ্ট্যের সাথে আবদ্ধ Text="{Binding Path=ConnectionName}"

public class ConnectionViewModel : ViewModelBase
{
    public string Name { get; set; }
    public string Password { get; set; }
}

public class MainWindowViewModel : ViewModelBase
{
    // List<ConnectionViewModel>...
    public CollectionView Connections { get; set; }
}

এক্সএএমএল কোড-পিছনে:

public partial class Window1
{
    public Window1()
    {
        InitializeComponent();
        DataContext = new MainWindowViewModel();
    }
}

তারপরে এক্সএএমএল:

<DataTemplate x:Key="listTemplate">
    <Grid>
        <ComboBox ItemsSource="{Binding Path=PhonebookEntries}"
            DisplayMemberPath="Name"
            SelectedValuePath="Name"
            SelectedValue="{Binding Path=PhonebookEntry}" />
        <TextBox Text="{Binding Path=Password}" />
    </Grid>
</DataTemplate>

<ItemsControl ItemsSource="{Binding Path=Connections}"
    ItemTemplate="{StaticResource listTemplate}" />

টেক্সটবক্স সবগুলি সঠিকভাবে আবদ্ধ হয় এবং কোনও সমস্যা ছাড়াই তাদের এবং ভিউমোডেলের মধ্যে ডেটা সরে যায়। এটি কেবল কম্বোবক্স যা কাজ করছে না।

আপনি ফোনবুক-এন্ট্রি ক্লাস সম্পর্কিত আপনার অনুমানের মধ্যে সঠিক।

আমি যে ধারণাটি করছি তা হ'ল আমার ডেটাম্প্লেট দ্বারা ব্যবহৃত ডেটা কনটেক্সটটি স্বয়ংক্রিয়ভাবে বাইন্ডিং হায়ারার্কির মাধ্যমে সেট হয়ে যায়, যাতে আমাকে স্পষ্ট করে এটিকে প্রতিটি আইটেমের জন্য সেট করতে না হয় ItemsControl। এটা আমার কাছে কিছুটা বোকা লাগবে।


এখানে একটি পরীক্ষার বাস্তবায়ন যা উপরের উদাহরণের ভিত্তিতে সমস্যাটি দেখায়।

এক্সএএমএল:

<Window x:Class="WpfApplication7.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <DataTemplate x:Key="itemTemplate">
            <StackPanel Orientation="Horizontal">
                <TextBox Text="{Binding Path=Name}" Width="50" />
                <ComboBox ItemsSource="{Binding Path=PhonebookEntries}"
                    DisplayMemberPath="Name"
                    SelectedValuePath="Name"
                    SelectedValue="{Binding Path=PhonebookEntry}"
                    Width="200"/>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ItemsControl ItemsSource="{Binding Path=Connections}"
            ItemTemplate="{StaticResource itemTemplate}" />
    </Grid>
</Window>

কোড-পিছনে :

namespace WpfApplication7
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            DataContext = new MainWindowViewModel();
        }
    }

    public class PhoneBookEntry
    {
        public string Name { get; set; }
        public PhoneBookEntry(string name)
        {
            Name = name;
        }
    }

    public class ConnectionViewModel : INotifyPropertyChanged
    {

        private string _name;

        public ConnectionViewModel(string name)
        {
            _name = name;
            IList<PhoneBookEntry> list = new List<PhoneBookEntry>
                                             {
                                                 new PhoneBookEntry("test"),
                                                 new PhoneBookEntry("test2")
                                             };
            _phonebookEntries = new CollectionView(list);
        }
        private readonly CollectionView _phonebookEntries;
        private string _phonebookEntry;

        public CollectionView PhonebookEntries
        {
            get { return _phonebookEntries; }
        }

        public string PhonebookEntry
        {
            get { return _phonebookEntry; }
            set
            {
                if (_phonebookEntry == value) return;
                _phonebookEntry = value;
                OnPropertyChanged("PhonebookEntry");
            }
        }

        public string Name
        {
            get { return _name; }
            set
            {
                if (_name == value) return;
                _name = value;
                OnPropertyChanged("Name");
            }
        }
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }

    public class MainWindowViewModel
    {
        private readonly CollectionView _connections;

        public MainWindowViewModel()
        {
            IList<ConnectionViewModel> connections = new List<ConnectionViewModel>
                                                          {
                                                              new ConnectionViewModel("First"),
                                                              new ConnectionViewModel("Second"),
                                                              new ConnectionViewModel("Third")
                                                          };
            _connections = new CollectionView(connections);
        }

        public CollectionView Connections
        {
            get { return _connections; }
        }
    }
}

আপনি যদি সেই উদাহরণটি চালান তবে আপনি যে আচরণের কথা বলছেন তা পাবেন। আপনি এটি সম্পাদনা করার সময় পাঠ্যবক্স তার বাধ্যতামূলক জরিমানা আপডেট করে, তবে কম্বোবক্স তা দেয় না। অত্যন্ত বিভ্রান্তিকরূপে দেখার কারণটি হ'ল আমি একমাত্র কাজটিই পিতামাতার ভিউমোডেলকে পরিচয় করিয়ে দিচ্ছি।

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

অর্থাৎ,

উইন্ডো -> ডেটা কনটেক্সট = মেইন
উইন্ডোভিউমোডেল .. আইটেমস -> ডেটা কনটেক্সট.ফোনবুকএন্ট্রি বাউন্ড
.... আইটেম -> ডেটা কনটেক্সট = ফোনবুকএন্ট্রি (স্পষ্টভাবে সম্পর্কিত)

এটি আমার অনুমানটিকে আরও ভাল (?) ব্যাখ্যা করে কিনা আমি জানি না।


আমার অনুমানের বিষয়টি নিশ্চিত করতে, পাঠ্যবক্সের বাঁধাই হতে হবে

<TextBox Text="{Binding Mode=OneWay}" Width="50" />

এবং এটি টেক্সটবক্সের বাইন্ডিং রুটটি দেখাবে (যা আমি ডেটা কনটেক্সটটির সাথে তুলনা করছি) এটি সংযোগভিউমোডেল উদাহরণ।

উত্তর:


192

আপনি ডিসপ্লে মেম্বারপথ এবং সিলেক্টভ্যালুপ্যাথটিকে "নাম" তে সেট করেছেন, তাই আমি ধরে নিলাম আপনার একটি সার্বজনীন সম্পত্তির নাম সহ একটি ফোনবুকঅন্ট্রি আছে।

আপনি কি আপনার সংযোগভিউমোডেল অবজেক্টে ডেটা কনটেক্সট সেট করেছেন?

আমি আপনার কোডটি অনুলিপি করেছি এবং কিছু ছোটখাট পরিবর্তন করেছি এবং এটি দুর্দান্ত কাজ করছে বলে মনে হচ্ছে। আমি ভিউ মডেলগুলি ফোনবুকইন্টি সম্পত্তি এবং কম্বোবক্সের পরিবর্তিত নির্বাচিত আইটেম সেট করতে পারি এবং আমি কম্বোবক্সে নির্বাচিত আইটেমটি পরিবর্তন করতে পারি এবং ভিউ মডেল ফোনবুকএন্ট্রি সম্পত্তি সঠিকভাবে সেট করা থাকে।

এখানে আমার এক্সএএমএল সামগ্রী রয়েছে:

<Window x:Class="WpfApplication6.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
<Grid>
    <StackPanel>
        <Button Click="Button_Click">asdf</Button>
        <ComboBox ItemsSource="{Binding Path=PhonebookEntries}"
                  DisplayMemberPath="Name"
                  SelectedValuePath="Name"
                  SelectedValue="{Binding Path=PhonebookEntry}" />
    </StackPanel>
</Grid>
</Window>

এবং এখানে আমার কোড পিছনে:

namespace WpfApplication6
{

    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            ConnectionViewModel vm = new ConnectionViewModel();
            DataContext = vm;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            ((ConnectionViewModel)DataContext).PhonebookEntry = "test";
        }
    }

    public class PhoneBookEntry
    {
        public string Name { get; set; }

        public PhoneBookEntry(string name)
        {
            Name = name;
        }

        public override string ToString()
        {
            return Name;
        }
    }

    public class ConnectionViewModel : INotifyPropertyChanged
    {
        public ConnectionViewModel()
        {
            IList<PhoneBookEntry> list = new List<PhoneBookEntry>();
            list.Add(new PhoneBookEntry("test"));
            list.Add(new PhoneBookEntry("test2"));
            _phonebookEntries = new CollectionView(list);
        }

        private readonly CollectionView _phonebookEntries;
        private string _phonebookEntry;

        public CollectionView PhonebookEntries
        {
            get { return _phonebookEntries; }
        }

        public string PhonebookEntry
        {
            get { return _phonebookEntry; }
            set
            {
                if (_phonebookEntry == value) return;
                _phonebookEntry = value;
                OnPropertyChanged("PhonebookEntry");
            }
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

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

কালেকশনভিউতে কোনও সমস্যা আছে? আমি আউটপুট কনসোলে একটি সতর্কতা লক্ষ্য করেছি:

System.Windows.Data সতর্কতা: 50: কালেকশনভিউ সরাসরি ব্যবহার সম্পূর্ণরূপে সমর্থিত নয়। বুনিয়াদি বৈশিষ্ট্যগুলি কিছু অদক্ষতার সাথে কাজ করে তবে উন্নত বৈশিষ্ট্যগুলি জানা বাগের মুখোমুখি হতে পারে। এই সমস্যাগুলি এড়াতে উদ্ভূত শ্রেণি ব্যবহারের কথা বিবেচনা করুন।

সম্পাদনা 2 (। নেট 4.5): ড্রপডাউনলিস্টের বিষয়বস্তু টপস্ট্রিংয়ের উপর ভিত্তি করে তৈরি করা যেতে পারে (ডিসপ্লে মেম্বারপাথের নয়), যদিও ডিসপ্লে মেম্বারপথ কেবলমাত্র নির্বাচিত এবং প্রদর্শিত আইটেমের জন্য সদস্যকে নির্দিষ্ট করে।


4
আমি সেই বার্তাটিও লক্ষ্য করেছি, তবে আমি ধরে নিয়েছিলাম যা আচ্ছাদিত ছিল তা বেসিক ডেটা বন্ডিং হত। আমি মনে করি না. :) আমি এখন _List.AsReadOnly () হিসাবে আপনি উল্লিখিতভাবে অনুরূপ ব্যবহার করে সম্পত্তিটি IList <টি হিসাবে >এবং সম্পত্তি প্রাপ্তিতে সম্পত্তি প্রকাশ করছি । এটি আসল পদ্ধতিটি যেমন আশা করতাম তেমন কাজ করে। এছাড়াও, এটি আমার মনকে অতিক্রম করেছে যে আইটেমসোর্স বাঁধাই ঠিকঠাক কাজ করার সময়, আমি কম্বোবক্সে নির্বাচিত আইটেমটি অ্যাক্সেস করার জন্য ভিউমোডেলে বর্তমান সম্পত্তিটি ব্যবহার করতে পারতাম। তবুও, এটি কম্বোবক্স সিলেক্টভ্যালু / নির্বাচিত আইটেম সম্পত্তি বাঁধাইয়ের মতো স্বাভাবিক বলে মনে হচ্ছে না।
জেফ বেনেট

4
আমি নিশ্চিত করতে পারি যে ItemsSourceসম্পত্তিটি আবদ্ধ, সংগ্রহটি পরিবর্তনযোগ্য, কেবলমাত্র পঠিত সংগ্রহের ক্ষেত্রে এটি কার্যকর হয়। আমার ক্ষেত্রে আমাকে এটি থেকে বদলে ObservableCollectionযেতে হয়েছিল ReadOnlyObservableCollection। বাদাম এটি .NET 3.5 - এটি 4.0
ক্রিসউইউ

77

কম্বোবক্সে ডেটা বাঁধতে

List<ComboData> ListData = new List<ComboData>();
ListData.Add(new ComboData { Id = "1", Value = "One" });
ListData.Add(new ComboData { Id = "2", Value = "Two" });
ListData.Add(new ComboData { Id = "3", Value = "Three" });
ListData.Add(new ComboData { Id = "4", Value = "Four" });
ListData.Add(new ComboData { Id = "5", Value = "Five" });

cbotest.ItemsSource = ListData;
cbotest.DisplayMemberPath = "Value";
cbotest.SelectedValuePath = "Id";

cbotest.SelectedValue = "2";

কম্বোডাটা দেখতে দেখতে:

public class ComboData
{ 
  public int Id { get; set; } 
  public string Value { get; set; } 
}

এই সমাধানটি আমার পক্ষে কাজ করে না। আইটেমসোর্স সূক্ষ্মভাবে কাজ করে, তবে পথের উত্সগুলি কম্বোডাটা মানগুলিতে সঠিকভাবে পুনঃনির্দেশ করছে না।
সোনোন

4
Idএবং শ্রেণীর ক্ষেত্র নয়, যেমন সম্পত্তিValue হতে হবে :public class ComboData { public int Id { get; set; } public string Value { get; set; } }
এডগার

24

আমার প্রথমে যা ছিল একটি অভিন্ন সমস্যা বলে মনে হয়েছিল, তবে এটি এনএইচবারনেট / ডাব্লুপিএফ সামঞ্জস্যতার সমস্যার কারণে হয়ে গেছে। সমস্যাটি ডব্লুপিএফ যেভাবে বস্তুর সাম্যের জন্য পরীক্ষা করে। আমি সিলেক্টভ্যালু এবং সিলেক্টভ্যালুপ্যাথ বৈশিষ্ট্যে আইটেম আইডি সম্পত্তি ব্যবহার করে আমার স্টাফটি কাজ করতে সক্ষম হয়েছি।

<ComboBox Name="CategoryList"
          DisplayMemberPath="CategoryName"
          SelectedItem="{Binding Path=CategoryParent}"
          SelectedValue="{Binding Path=CategoryParent.ID}"
          SelectedValuePath="ID">

চেসটার, ডাব্লুপিএফ কম্বোবক্স - সিলেক্টডাইম , সিলেক্টভ্যালু এবং এনএইচবারনেটের সাথে সিলেক্টভ্যালিউপ্যাথের ব্লগ পোস্টটি দেখুন ।


লিঙ্কটি মৃত এবং সম্পাদনা সারিতে পূর্ণ, সুতরাং আমি বর্তমান লিঙ্কটি এখানে রাখছি
blog

1

আমার একটি একই সমস্যা ছিল যেখানে সিলেক্টড আইটেমটি কখনই আপডেট হয় না।

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

public override bool Equals(object obj)
{
    return this.Id == (obj as MyCustomObject).Id;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.