SelectedItem / SelectedValue güncelleştirmek görünmüyor bir ComboBox var.
ComboBox ItemsSource, ViewModel sınıfında bir grup RAS telefon defteri girdisini CollectionView olarak listeleyen bir özelliğe bağlıdır. Sonra (ayrı zamanlarda) hem SelectedItem
veya SelectedValue
ViewModel başka bir özelliğine bağlı ettik . Veritabanının ayarladığı değerlerde hata ayıklamak için save komutuna bir MessageBox ekledim, ancak SelectedItem
/ SelectedValue
bağlama ayarlanmadı.
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 koleksiyonu yapıcıda bir iş nesnesinden başlatılıyor. ComboBox XAML şuna benzer:
<ComboBox ItemsSource="{Binding Path=PhonebookEntries}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding Path=PhonebookEntry}" />
Ben sadece ComboBox görüntülenen gerçek dize değeri, bu VPN bağlantısı yapmak istediğinizde RAS geçmesi gereken değer DisplayMemberPath
ve bu nedenle SelectedValuePath
hem Name özelliği olduğu gibi nesnenin diğer özellikleri ilgileniyorum ConnectionViewModel. ComboBox, DataContext öğesinin ViewModel örneğine ayarlanmış olan bir Pencere üzerindeki bir DataTemplate
uygulamasındadır ItemsControl
.
ComboBox öğelerin listesini doğru görüntüler ve kullanıcı arayüzünde sorunsuz bir tane seçebilirim. Ancak komuttan ileti kutusunu görüntülediğimde, PhonebookEntry özelliğinin hala ilk değeri var, ComboBox öğesinden seçilen değer değil. Diğer TextBox örnekleri iyi güncelleniyor ve MessageBox içinde görüntüleniyor.
ComboBox veritabanında eksik olan ne? Çok fazla arama yaptım ve yanlış yaptığım hiçbir şey bulamıyorum.
Gördüğüm davranış bu, ancak benim belirli bağlamımda bir sebepten dolayı çalışmıyor.
CollectionView
ConnectionViewModels olan bir MainWindowViewModel var . Arkadaki MainWindowView.xaml dosyasında, DataContext'i MainWindowViewModel olarak ayarladım. MainWindowView.xaml, ItemsControl
ConnectionViewModels koleksiyonuna bağlıdır. ComboBox yanı sıra diğer bazı TextBox tutan bir DataTemplate var. TextBox'lar doğrudan kullanarak ConnectionViewModel özelliklerine bağlıdır 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; }
}
Arkasındaki XAML kodu:
public partial class Window1
{
public Window1()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
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}" />
TextBox'ların tümü doğru bir şekilde bağlanır ve veriler ve ViewModel arasında sorunsuz bir şekilde hareket eder. Sadece ComboBox çalışmıyor.
PhonebookEntry sınıfı ile ilgili varsayımlarınız doğrudur.
Yaptığım varsayım, benim DataTemplate tarafından kullanılan DataContext otomatik olarak bağlama hiyerarşisi ile ayarlanır, böylece açıkça her öğe için ayarlamak zorunda değilsiniz ItemsControl
. Bu bana biraz aptalca geliyor.
Yukarıdaki örneği temel alarak sorunu gösteren bir test uygulaması.
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>
Arka plan 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; }
}
}
}
Bu örneği çalıştırırsanız, bahsettiğim davranışı elde edersiniz. TextBox, ciltleme düzenini düzenlediğinizde güncelleştirir ancak ComboBox değiştirmez. Gerçekten yaptığım tek şey olarak görmek çok kafa karıştırıcı bir üst ViewModel tanıtmaktır.
Şu anda bir DataContext alt öğeye bağlı bir öğenin DataContext olarak bu çocuğa sahip olduğu izlenimi altında çalışıyorum. Bunu şu ya da bu şekilde temizleyen herhangi bir belge bulamıyorum.
yani,
Pencere -> DataContext = MainWindowViewModel
..Items -> DataContext.PhonebookEntries'e Bağlanın
.... Öğe -> DataContext = PhonebookEntry (örtük olarak ilişkili)
Bu varsayımı daha iyi açıklıyor mu bilmiyorum (?).
Varsayımı onaylamak için, TextBox'ın bağlayıcılığını
<TextBox Text="{Binding Mode=OneWay}" Width="50" />
Ve bu TextBox bağlama kökü gösterecektir (ki ben DataContext ile karşılaştırıyorum) ConnectionViewModel örneğidir.
<
T>
ve _list.AsReadOnly () kullanarak özellik getter özellikleri belirttiğiniz şekilde benzer maruz bırakıyorum. Orijinal yöntemin olmasını umduğum gibi çalışıyor. Ayrıca, ItemsSource bağlama iyi çalışırken, ben sadece ComboBox seçili öğeye erişmek için ViewModel Current özelliğini kullanabileceğini aklımdan geçti. Yine de, ComboBoxes SelectedValue / SelectedItem özelliğini bağlamak kadar doğal gelmiyor.