#c# #wpf #data-binding #datagrid #combobox
#c# #wpf #привязка к данным #datagrid #поле со списком
Вопрос:
У меня есть поле со списком, в котором содержится список StrategyViewModels. StrategyViewModel имеет внутри себя наблюдаемую коллекцию StrategyParameterViewModels. У меня есть StrategyViewModel с именем SelectedStrategy, который я привязал к свойству SelectedItem в выпадающем списке. Когда пользователь выбирает стратегию из выпадающего списка, я хотел бы установить itemsource сетки данных в StrategyParameters внутри этой стратегии. Я перепробовал все разные способы, но, похоже, ничего не работает.
Вот XAML:
<ComboBox Height="23" Margin="0,12,0,0" Name="cbxStrats" VerticalAlignment="Top" ItemsSource="{Binding Strategies}" DisplayMemberPath="Name" SelectedItem="{Binding Path=SelectedStrategy,Mode=TwoWay}" />
<DataGrid AutoGenerateColumns="False" Margin="12,97,14,35" Name="dgSettings" ItemsSource="{Binding SelectedStrategy.Parameters, Mode=TwoWay}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" IsReadOnly="True"/>
<DataGridTextColumn Header="Value" Binding="{Binding Path=Value}" IsReadOnly="False"/>
</DataGrid.Columns>
</DataGrid>
Вот стратегия ViewModel:
public class StrategyViewModel : ViewModelBase
{
public StrategyObject Strategy { get; set; }
public int Id
{
get { return Strategy.Id; }
set
{
if (value == Strategy.Id)
return;
Strategy.Id = value;
OnPropertyChanged("Id");
}
}
public string Name
{
get { return Strategy.Name; }
set
{
if (value == Strategy.Name)
return;
Strategy.Name = value;
OnPropertyChanged("Name");
}
}
public ObservableCollection<StrategyParameterViewModel> Parameters { get { return _parameters; } }
public ObservableCollection<StrategyParameterViewModel> _parameters;
public StrategyViewModel()
{
Strategy = new StrategyObject();
_parameters = new ObservableCollection<StrategyParameterViewModel>();
}
public StrategyViewModel(StrategyObject o, IEnumerable<StrategyParameterObject> pms)
{
Strategy = o;
_parameters = new ObservableCollection<StrategyParameterViewModel>();
foreach (StrategyParameterObject s in pms)
{
_parameters.Add(new StrategyParameterViewModel(s));
}
}
}
И вот параметр StrategyParameter ViewModel:
public class StrategyParameterViewModel : ViewModelBase
{
public StrategyParameterObject StrategyParameter { get; set; }
public int Id
{
get { return StrategyParameter.Id; }
set
{
if (value == StrategyParameter.Id)
return;
StrategyParameter.Id = value;
OnPropertyChanged("Id");
}
}
public int StrategyId
{
get { return StrategyParameter.StrategyId; }
set
{
if (value == StrategyParameter.StrategyId)
return;
StrategyParameter.StrategyId = value;
OnPropertyChanged("StrategyId");
}
}
public string Name
{
get { return StrategyParameter.Name; }
set
{
if (value == StrategyParameter.Name)
return;
StrategyParameter.Name = value;
OnPropertyChanged("Name");
}
}
public string Value
{
get { return StrategyParameter.Value; }
set
{
if (value == StrategyParameter.Value)
return;
StrategyParameter.Value = value;
OnPropertyChanged("Value");
}
}
public StrategyParameterViewModel()
{
StrategyParameter = new StrategyParameterObject();
}
public StrategyParameterViewModel(StrategyParameterObject o)
{
StrategyParameter = o;
}
}
Ответ №1:
Проблема в том, что вы пытаетесь настроить двустороннюю привязку со свойством, доступным только для чтения. Вам нужно либо добавить параметр для SelectedStrategy.Параметры или использовать одностороннюю привязку к источнику itemssource для datagrid.
Комментарии:
1. боже, я чувствую себя глупо. Я установил для него значение oneway, и оно все еще не работало. Затем я понял, что не реализовал INotifyChanged в моем объекте SelectedStrategy. Как только я это сделал, все работает отлично.
Ответ №2:
С моей точки зрения, я не думаю, что вы делаете что-то неправильно в отношении вашего XAML.
Общеизвестно, что привязка данных является сложной задачей. Я предлагаю добавить PresentationTraceSources, чтобы получить больше отладочной информации о том, что найдено. Это отправит несколько строк данных о результатах привязки к вашему окну вывода.
<ComboBox Height="23" Margin="0,12,0,0" Name="cbxStrats" VerticalAlignment="Top" DisplayMemberPath="Name">
<ComboBox.ItemsSource>
<Binding Path="Strategies" PresentationTraceSources.TraceLevel="High"/>
</ComboBox.ItemsSource>
<ComboBox.SelectedItem>
<Binding Path="SelectedStrategy" Mode="TwoWay" PresentationTraceSources.TraceLevel="High"/>
</ComboBox.SelectedItem>
</ComboBox>
<DataGrid AutoGenerateColumns="False" Margin="12,97,14,35" Name="dgSettings">
<DataGrid.ItemsSource>
<Binding Path="SelectedStrategy.Parameters" Mode="TwoWay" PresentationTraceSources.TraceLevel="High"/>
</DataGrid.ItemsSource>
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" IsReadOnly="True"/>
<DataGridTextColumn Header="Value" Binding="{Binding Path=Value}" IsReadOnly="False"/>
</DataGrid.Columns>
</DataGrid>
Кроме того, может помочь WPF Inspector, поскольку вы можете настраивать выражения привязки данных в режиме реального времени при запуске вашего реального приложения.http://wpfinspector.codeplex.com /