SelectedItem / SelectedValue를 업데이트하지 않는 ComboBox가 있습니다.
ComboBox ItemsSource는 RAS 전화 번호부 항목을 CollectionView로 나열하는 ViewModel 클래스의 속성에 바인딩됩니다. 그런 다음 ViewModel 의 SelectedItem
또는 SelectedValue
다른 속성에 (별도로) 바인딩했습니다 . 데이터 바인딩으로 설정된 값을 디버깅하기 위해 MessageBox를 save 명령에 추가했지만 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}" />
I 만 실제 문자열 값에 관심이 콤보 상자에 표시되지이 같은 개체의 다른 특성은 내가 따라서, VPN 연결을 할 때이 RAS에 걸쳐 통과하는 데 필요한 값 DisplayMemberPath
과 SelectedValuePath
의 Name 속성 모두는 ConnectionViewModel. ComboBox는 DataContext가 ViewModel 인스턴스로 설정된 Window에 DataTemplate
적용됩니다 ItemsControl
.
ComboBox는 항목 목록을 올바르게 표시하며 UI에서 아무 문제없이 선택할 수 있습니다. 그러나 명령에서 메시지 상자를 표시 할 때 PhonebookEntry 속성에는 ComboBox에서 선택한 값이 아니라 여전히 초기 값이 있습니다. 다른 TextBox 인스턴스가 정상적으로 업데이트되어 MessageBox에 표시됩니다.
ComboBox의 데이터 바인딩에서 무엇을 놓치고 있습니까? 나는 많은 검색을 해왔고 내가 잘못하고있는 것을 찾지 못하는 것 같습니다.
이것은 내가보고있는 동작이지만 특정 상황에서 어떤 이유로 작동하지 않습니다.
CollectionView
ConnectionViewModels 가있는 MainWindowViewModel이 있습니다 . MainWindowView.xaml 파일 코드 숨김에서 DataContext를 MainWindowViewModel로 설정했습니다. MainWindowView.xaml은 ItemsControl
ConnectionViewModels 컬렉션에 바인딩됩니다. ComboBox와 다른 TextBox를 포함하는 DataTemplate이 있습니다. TextBox는을 사용하여 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}" />
TextBox는 모두 올바르게 바인딩되며 데이터는 문제없이 ViewModel과 ViewModel간에 이동합니다. 작동하지 않는 것은 ComboBox뿐입니다.
PhonebookEntry 클래스에 대한 가정이 정확합니다.
내가 만들고있는 가정은 내 DataTemplate에서 사용하는 DataContext가 바인딩 계층을 통해 자동으로 설정되므로의 각 항목에 대해 명시 적으로 설정할 필요가 없다는 것 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>
코드 숨김 :
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는 편집 할 때 바인딩이 제대로 업데이트되지만 ComboBox는 바인딩을 업데이트하지 않습니다. 내가 한 유일한 것으로 보는 것이 매우 혼란 스럽다면 부모 ViewModel을 소개하는 것입니다.
현재 DataContext의 자식에 바인딩 된 항목에 해당 자식이 DataContext라는 인상을 받고 있습니다. 이 방법을 정리하는 문서를 찾을 수 없습니다.
즉,
Window-> DataContext = MainWindowViewModel
..Items- > DataContext.PhonebookEntries에 바인딩 됨
.... Item- > DataContext = PhonebookEntry (내재적으로 연결됨 )
그게 내 가정을 더 잘 설명하는지 모르겠습니다 (?).
내 가정을 확인하려면 TextBox의 바인딩을 다음과 같이 변경하십시오.
<TextBox Text="{Binding Mode=OneWay}" Width="50" />
그리고 이것은 TextBox 바인딩 루트 (DataContext와 비교하고 있음)가 ConnectionViewModel 인스턴스임을 보여줍니다.
<
T로>
속성을 표시하고 언급 한 것과 비슷한 _list.AsReadOnly ()를 사용하여 getter 속성에 속성을 노출합니다 . 원래의 방법으로 기대했던대로 작동합니다. 또한 ItemsSource 바인딩이 제대로 작동하는 동안 ViewModel의 Current 속성을 사용하여 ComboBox에서 선택한 항목에 액세스 할 수 있다고 생각했습니다. 여전히 ComboBoxes SelectedValue / SelectedItem 속성을 바인딩하는 것만 큼 자연스럽지 않습니다.