Я знаю, что есть много вопросов об этом, я гарантировал, что каждый ответ был предпринят. У меня нет большого опыта работы с WPF, и никто другой в моей команде, поэтому я уверен, что сделал глупую ошибку и не вижу ее. Я добавляю новую функцию в этот проект, который я взял на себя, и преобразовал код спагетти в начало решения MVVM. У меня есть модель, которая основана на DeSerialization документа XML и ViewModel. У них в настоящее время есть данные, которые мне нужны для UserControl. Поэтому у меня DataContext установлен в Code Behind. В этой MsClassification изначально устанавливается значение «UN». Я меняю combobox на что-то еще и использую кнопку для повторного чтения XML, который возвращает MsClassification обратно в «UN», однако View не обновляется. Интересно, что если я установил MsLoggingLevel на что-то еще и перечитал XML, он обновит оба значения.WPF-привязка не обновляется для одного объекта
XAML:
<TabItem Header="Init" HorizontalAlignment="Left" Height="25" VerticalAlignment="Top" Width="78" Margin="0" ClipToBounds="True">
<Grid Background="#FFE5E5E5" ClipToBounds="True">
<TreeView x:Name="AssessorToolWindow_InitTree" Margin="0" BorderThickness="0" ClipToBounds="True" DataContext="{Binding Path=VSParentReference.InitRules.Init}">
<TreeViewItem Header="Excluded Files" ItemsSource="{Binding Path=MsExcludedFiles}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TreeViewItem Header ="{Binding}"/>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem Header="Included Files" ItemsSource="{Binding Path=MsIncludedFiles, Mode=TwoWay}">
<TreeViewItem.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="{Binding}"/>
</DataTemplate>
</TreeViewItem.ItemTemplate>
</TreeViewItem>
<TreeViewItem Header="Project Path">
<TreeViewItem Header="{Binding Path=MsRootProjectDirectory, Mode=TwoWay}"/>
</TreeViewItem>
<TreeViewItem Header="Classification">
<ComboBox
ItemsSource="{Binding Path=ClassificationLevels}"
SelectedValue="{Binding Path=MsClassification}"
IsSynchronizedWithCurrentItem="True" />
</TreeViewItem>
<TreeViewItem Header="Log Level">
<ComboBox
ItemsSource="{Binding Path=LoggerLevels}"
SelectedItem="{Binding Path=MsLogLevel}"
IsSynchronizedWithCurrentItem="True"
/>
</TreeViewItem>
</TreeView>
</Grid>
</TabItem>
Code-за:
[XmlArrayItem("EXC"),
XmlArray("ExcludedFiles")]
public ObservableCollection<string> MsExcludedFiles
{
get
{
return _msExcludedFiles;
}
set
{
if (value != _msExcludedFiles)
{
_msExcludedFiles = value;
NotifyPropertyChanged("MsExcludedFiles");
}
}
}
[XmlArrayItem("INC"),
XmlArray("IncludedFiles")]
public ObservableCollection<string> MsIncludedFiles
{
get
{
return _msIncludedFiles;
}
set
{
if (value != _msIncludedFiles)
{
_msIncludedFiles = value;
NotifyPropertyChanged("MsIncludedFiles");
}
}
}
[XmlElement(ElementName = "ProjectPath")]
public string MsRootProjectDirectory
{
get
{
return _msRootProjectDirectory;
}
set
{
if (value != _msRootProjectDirectory)
{
_msRootProjectDirectory = value;
NotifyPropertyChanged("MsRootProjectDirectory");
}
}
}
[XmlElement(ElementName = "LogLevel")]
public string MsLogLevel
{
get { return _msLogLevel; }
set
{
if (value != _msLogLevel)
{
_msLogLevel = value;
NotifyPropertyChanged("MsLogLevel");
}
}
}
[XmlElement(ElementName = "Classification")]
public String MsClassification
{
get
{
return classification;
}
set
{
if (value != classification)
{
classification = value;
NotifyPropertyChanged("MsClassification");
}
}
}
protected virtual void NotifyPropertyChanged(string p)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(p));
}
Fody определенно выглядит как хороший инструмент. Никогда не слышал об этом, но похоже, что это действительно может сэкономить массу времени. – mcy
Я посмотрю на Фоди. ClassifcationLevels необходимо установить один раз, а затем выполнить. ClassificationLevel должен быть двухсторонним, поэтому я добавил это. Без изменений. Я реализую INotifyPropertyChanged. Один вопрос по этому вопросу и вопрос о нобе. Должен ли я реализовывать INotifyPropertyChanged во всех классах (VSParentReference.InitRules) –
Да. Каждый класс, который должен быть привязан к элементу управления, должен его реализовать. Общее правило состоит в том, чтобы позволить каждой виртуальной машине реализовать его, и только VM связаны. Fody избавит вас от кучи времени. – user853710