ฉันมี ComboBox ที่ดูเหมือนจะไม่อัพเดทค่า SelectedItem / SelectedValue
ComboBox ItemsSource ถูกผูกไว้กับคุณสมบัติบนคลาส ViewModel ที่แสดงรายการสมุดโทรศัพท์ RAS จำนวนมากเป็น CollectionView จากนั้นฉันได้ผูก (ในเวลาที่แยกต่างหาก) ทั้งคุณสมบัติSelectedItem
หรือSelectedValue
ไปยังคุณสมบัติอื่นของ ViewModel ฉันได้เพิ่ม MessageBox ลงในคำสั่งบันทึกเพื่อตรวจแก้จุดบกพร่องค่าที่กำหนดโดย databinding แต่ไม่มีการตั้งค่าSelectedItem
/ การSelectedValue
ผูก
คลาส ViewModel มีลักษณะดังนี้:
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 ในตัวสร้างจากวัตถุธุรกิจ ComboBox XAML มีลักษณะเช่นนี้:
<ComboBox ItemsSource="{Binding Path=PhonebookEntries}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding Path=PhonebookEntry}" />
ฉันสนใจเฉพาะค่าสตริงจริงที่แสดงใน ComboBox ไม่ใช่คุณสมบัติอื่น ๆ ของวัตถุเนื่องจากเป็นค่าที่ฉันต้องส่งผ่านไปยัง RAS เมื่อฉันต้องการทำการเชื่อมต่อ VPN ด้วยเหตุนี้DisplayMemberPath
และSelectedValuePath
เป็นทั้งชื่อคุณสมบัติของ ConnectionViewModel ComboBox อยู่ในDataTemplate
การนำไปใช้ItemsControl
กับหน้าต่างที่ DataContext ได้รับการตั้งค่าเป็นอินสแตนซ์ ViewModel
ComboBox แสดงรายการของรายการอย่างถูกต้องและฉันสามารถเลือกหนึ่งรายการใน UI โดยไม่มีปัญหา อย่างไรก็ตามเมื่อฉันแสดงกล่องข้อความจากคำสั่งคุณสมบัติ PhonebookEntry ยังคงมีค่าเริ่มต้นอยู่ในนั้นไม่ใช่ค่าที่เลือกจาก ComboBox อินสแตนซ์ของกล่องข้อความอื่นกำลังปรับปรุงและแสดงใน MessageBox
ฉันขาดอะไรบ้างกับการบันทึกข้อมูล ComboBox? ฉันทำการค้นหาจำนวนมากและดูเหมือนจะไม่พบสิ่งใดที่ฉันทำผิด
นี่คือพฤติกรรมที่ฉันเห็น แต่มันไม่ทำงานด้วยเหตุผลบางอย่างในบริบทเฉพาะของฉัน
ฉันมี MainWindowViewModel ซึ่งมีCollectionView
ConnectionViewModels อยู่ ในโค้ดไฟล์ MainWindowView.xaml ฉันตั้งค่า DataContext เป็น MainWindowViewModel MainWindowView.xaml มีข้อItemsControl
ผูกมัดกับคอลเลกชันของ ConnectionViewModels ฉันมี DataTemplate ที่เก็บ ComboBox และ TextBox อื่น ๆ TextBoxes จะผูกพันโดยตรงกับคุณสมบัติของ ConnectionViewModel 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; }
}
โค้ดเบื้องหลังของ XAML:
public partial class Window1
{
public Window1()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
จากนั้น 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}" />
กล่องข้อความทั้งหมดผูกอย่างถูกต้องและข้อมูลย้ายระหว่างพวกเขาและ ViewModel โดยไม่มีปัญหา มันเป็นเพียง ComboBox ที่ไม่ทำงาน
คุณถูกต้องในสมมุติฐานของคุณเกี่ยวกับคลาส PhonebookEntry
สมมติฐานที่ผมทำก็คือว่า DataContext ใช้โดย DataTemplate ItemsControl
ของฉันคือการตั้งค่าโดยอัตโนมัติผ่านลำดับชั้นผูกพันเพื่อที่ฉันจะได้ไม่ต้องกำหนดอย่างชัดเจนว่ามันสำหรับแต่ละรายการใน ที่ดูเหมือนจะโง่สำหรับฉัน
นี่คือการทดสอบการใช้งานที่แสดงให้เห็นถึงปัญหาตามตัวอย่างข้างต้น
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>
behind รหัส :
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; }
}
}
}
หากคุณเรียกใช้ตัวอย่างนั้นคุณจะได้รับพฤติกรรมที่ฉันพูดถึง กล่องข้อความปรับปรุงการรวมที่ดีเมื่อคุณแก้ไข แต่ ComboBox ไม่ การดูสับสนมากเพราะสิ่งเดียวที่ฉันทำคือแนะนำ ViewModel ของผู้ปกครอง
ขณะนี้ฉันกำลังทำงานภายใต้การแสดงผลที่รายการที่ผูกกับชายด์ของ DataContext มีชายด์นั้นเป็น DataContext ฉันไม่พบเอกสารใด ๆ ที่ล้างสิ่งนี้ไม่ทางใดก็ทางหนึ่ง
กล่าวคือ
หน้าต่าง -> DataContext = MainWindowViewModel
..Items -> ที่ถูกผูกไว้กับ DataContext.PhonebookEntries
.... รายการ -> DataContext = PhonebookEntry (เชื่อมโยงโดยนัย)
ฉันไม่รู้ว่าจะอธิบายสมมติฐานของฉันได้ดีกว่านี้ไหม (?)
เพื่อยืนยันสมมติฐานของฉันเปลี่ยนการเชื่อมโยงกล่องข้อความให้เป็น
<TextBox Text="{Binding Mode=OneWay}" Width="50" />
และสิ่งนี้จะแสดงการผูกกล่องข้อความ (ซึ่งฉันกำลังเปรียบเทียบกับ DataContext) คืออินสแตนซ์ ConnectionViewModel
<
T>
และในคุณสมบัติ getter โดยใช้ _list.AsReadOnly () คล้ายกับที่คุณพูดถึง มันทำงานได้เหมือนที่ฉันคาดหวังว่าจะมีวิธีดั้งเดิม นอกจากนี้ฉันยังทราบว่าในขณะที่การเชื่อมโยงรายการแหล่งข้อมูลทำงานได้ดีฉันสามารถใช้คุณสมบัติปัจจุบันใน ViewModel เพื่อเข้าถึงรายการที่เลือกใน ComboBox ถึงกระนั้นมันก็ไม่ได้รู้สึกเป็นธรรมชาติที่มีผลผูกพันคุณสมบัติ ComboBoxes SelectedValue / SelectedItem