SORU
18 ŞUBAT 2009, ÇARŞAMBA


Bağlama WPF Özel bir Liste için ComboBox

Selectedıtem/SelectedValue güncelleştirmek için görünmüyor bir ComboBox var.

ComboBox İtemsSource bağlı bir mülk üzerinde bir ViewModel sınıfı listeleyen bir demet RAS telefon rehberi girdisi olarak bir CollectionView, o zaman ben bağlı (ayrı zamanlarda) hem Selectedıtem veya SelectedValue başka bir özelliğin ViewModel. Kaydet komutunu değerleri veri bağlama tarafından belirlenen hata ayıklama için bir MessageBox ekledim ama Selectedıtem/SelectedValue bağlama ayarlı değil.

ViewModel sınıfı şuna benzer:

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

_phonebookEntries toplama bir iş nesnesinin kurucu başlatıldığını ediliyor. ComboBox XAML şuna benzer:

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

Benim tek dertleri gerçek dize değeri görüntülenen ComboBox, diğer özellikleri nesne olarak bu değeri ihtiyacım var pas geçmek RAS zaman yapmak istiyorum VPN bağlantısı, dolayısıyla DisplayMemberPath ve SelectedValuePath hem Adı özelliği ConnectionViewModel. ComboBox bir DataTemplate. DataContext ViewModel bir örneği için ayarlanmış olan bir Pencere üzerinde bir ItemsControl uygulanır.

ComboBox düzgün öğe listesi görüntüler ve hiçbir sorun ile UI birini seçebilirsiniz. Komut ileti kutusu görüntülemek, ancak PhonebookEntry özelliğini hala ComboBox dan seçilen değere başlangıç değeri vardır. Diğer TextBox örnekleri güzel güncellenmesi ve MessageBox görüntüleniyor.

ComboBox veri bağlama ile neyi kaçırıyorum? Arama Bir çok şey yaptım ve yanlış yaptığım bir şey bulamıyorum.


Bu görüşüyorum davranıştır, ancak benim özellikle bağlamda nedense işe yaramıyor.

ConnectionViewModels bir CollectionView olan bir MainWindowViewModel var. Bu MainWindowView.arka planda kodlama dosya xaml, MainWindowViewModel için DataContext kurdum. Bu MainWindowView.xaml bir ItemsControl ConnectionViewModels toplanmasına bağlı. ComboBox yanı sıra bazı diğer metin Kutularının tutan bir DataTemplate var. Metin doğrudan ConnectionViewModel Metin=kullanma özelliklerine bağlıdır"{Binding Path=Dosyası}".

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

XAML arkasında kod:

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

Daha sonra XAML:

<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}" />

Bu doğru bağlamak tüm metin Kutularının ve veri hiçbir sorun ile onları ve ViewModel arasında hareket eder. Sadece çalışmayan ComboBox.

PhonebookEntry sınıfı ile ilgili söylediklerin doğru.

Ben yapıyorum varsayım DataContext benim DataTemplate kullandığı açıkça ItemsControl her madde için ayarlayın gerek yok, böylece otomatik olarak bağlama hiyerarşisi aracılığıyla ayarlanır. Bence bu biraz saçma gibi görünüyor.


Burada sorunu gösteren bir test uygulaması, yukarıdaki örneğe dayalı.

XAML:

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

-Arkasında kod:

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

Eğer bu örnek çalıştırırsanız, bahsettiğim davranış olacaktır. Metin düzenleme bağlayıcı ince güncellemeleri, ama ComboBox değil. Çok kafa karıştırıcı.

Şu anda bir öğe bir DataContext çocuk bağlı DataContext olarak o çocuk izlenimi altında emekçi ediyorum. Öyle ya da böyle bu temizler herhangi bir belge bulamadım.

I. e

Pencere ->DataContext = MainWindowViewModel
Öğeleri -^... DataContext bağlı.PhonebookEntries
....Madde ->= PhonebookEntry (dolaylı olarak ilişkili) DataContext

Eğer benim varsayımım daha iyi açıklar mı bilmiyorum?


Benim varsayım teyit etmek için Metin bağlantısını değiştirin

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

Ve bu bağlama kök DataContext için karşılaştırıyorum) ConnectionViewModel örnek Metin gösterecektir.

CEVAP
18 ŞUBAT 2009, ÇARŞAMBA


Bu DisplayMemberPath ve SelectedValuePath ayarlayın "Adı" bir sınıf olduğunu varsayıyorum, ortak bir özellik Adı ile PhoneBookEntry.

ConnectionViewModel nesnesinin DataContext belirlediniz mi?

Sen ve bazı küçük değişiklikler kod yaptı ve gayet iyi iş gibi görünüyor kopyaladım. Combobox değişiklikleri viewmodels PhoneBookEnty özelliği seçili öğeyi ayarlamak, ve combobox Seçili öğeyi değiştirmek ve görünüm modelleri PhoneBookEntry özelliği doğru olarak ayarlanır.

İşte benim xaml:

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

Ve burada benim kod:

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

Düzenleme:Geoffs ikinci örnek bana biraz tuhaf görünüyor çalışmak için görünmüyor. Ben Eğerbu ConnectionViewModel üzerinde PhonebookEntries özelliği türü ReadOnlyCollection olacak şekilde değiştirinbu iki yönlü combobox üzerinde SelectedValue bağlayıcı gayet iyi çalışıyor.

Belki CollectionView ile ilgili bir sorun var mı? Bir uyarı çıkışı konsol fark ettim: "Sistemi.Windows.Veri Uyarı: 50 : CollectionView doğrudan tam olarak desteklenmiyor. Temel bazı yetersizlikler, ama gelişmiş özellikleri bilinen hatalar karşılaşabilirsiniz rağmen çalışma özellikleri. Bu sorunları önlemek için türetilmiş bir sınıf kullanmayı düşünün."

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • boogie2988

    boogie2988

    6 NİSAN 2006
  • Jon Reed

    Jon Reed

    14 AĞUSTOS 2006
  • Kim Barbin

    Kim Barbin

    3 Mayıs 2012