I have a Parent ViewModel which contains a child view model object inside with some enum,
When I open the UI I see that the enum value not renders as expected from the RaisePropertyChanged event on first time loading, however, after setting a value from the UI the value changes and renders as expected.
Parent VM xaml
<UserControl x:Class="RemoteDebugger.App.Views.ConfigurationControl"
d:DataContext="{d:DesignInstance viewModels:ConfigurationViewModel}">
<Grid>
//Some properties...
<local:ProjectEditor Grid.Row="5" Grid.Column="1" BorderBrush="#FFCFCBCB" BorderThickness="0,1,0,1" Grid.ColumnSpan="3" DataContext="{Binding MainProject,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ></local:ProjectEditor>
</Grid>
Parent VM cs
using RemoteDebugger.App.Utils;
using System.Collections.Generic;
using System.IO;
using System.Windows.Input;
using Microsoft.Win32;
using RemoteDebugger.Model;
using RemoteDebugger.Model.DataStructures;
namespace RemoteDebugger.App.ViewModels
{
public class ConfigurationViewModel : BaseViewModel
{
private ICommand _saveConfiguration;
private ICommand _loadConfiguration;
private Configuration _configuration;
private ProjectViewModel _mainProject;
private ExtraProjectsViewModel _extraProjects;
public ConfigurationViewModel()
{
_configuration = RemoteDebuggerManager.Instance.Configuration;
_mainProject = new ProjectViewModel(_configuration.MainProject);
_extraProjects = new ExtraProjectsViewModel(_configuration.ExtraProjectsToCopy);
}
public ICommand SaveConfiguration
{
get
{
return _saveConfiguration ??= new Command(o =>
{
_configuration.MainProject = _mainProject.Project;
_configuration.ExtraProjectsToCopy = _extraProjects.Projects;
RemoteDebuggerManager.Instance.SaveConfigurations();
});
}
}
public ICommand LoadConfiguration
{
get
{
return _loadConfiguration ??= new Command(o =>
{
var fd = new OpenFileDialog
{
Multiselect = false,
Filter = "XML Files (*.xml)|*.xml",
InitialDirectory = ConfigurationHandler.ConfigurationFolder
};
var path = fd.ShowDialog();
if (path == null || !File.Exists(fd.FileName))
return;
_configuration = RemoteDebuggerManager.Instance.LoadConfigurations(fd.FileName);
UpdateView();
});
}
}
private void UpdateView()
{
OsBits = _configuration.OsBits;
VisualStudioVersion = _configuration.VisualStudioVersion;
CopyExtraPaths = _configuration.CopyExtraPaths;
Ip = _configuration.ControllerIp;
_mainProject.Project = _configuration.MainProject;
_extraProjects.Projects = _configuration.ExtraProjectsToCopy;
}
public string VisualStudioVersion
{
get => _configuration.VisualStudioVersion;
set
{
_configuration.VisualStudioVersion = value;
RaisePropertyChanged(nameof(VisualStudioVersion));
}
}
public string OsBits
{
get => _configuration.OsBits;
set
{
_configuration.OsBits = value;
RaisePropertyChanged(nameof(OsBits));
}
}
public string Ip
{
get => _configuration.ControllerIp;
set
{
_configuration.ControllerIp = value;
RaisePropertyChanged(nameof(Ip));
}
}
public string WaitForDebugFileDestination
{
get => _configuration.WaitForDebugFileDestination;
set
{
_configuration.WaitForDebugFileDestination = value;
RaisePropertyChanged(nameof(WaitForDebugFileDestination));
}
}
public bool CopyExtraPaths
{
get => _configuration.CopyExtraPaths;
set
{
_configuration.CopyExtraPaths = value;
RaisePropertyChanged(nameof(CopyExtraPaths));
}
}
public ProjectViewModel MainProject
{
get => _mainProject;
set
{
_mainProject = value;
RaisePropertyChanged(nameof(MainProject));
}
}
public ExtraProjectsViewModel ExtraProjects
{
get => _extraProjects;
set
{
_extraProjects = value;
RaisePropertyChanged(nameof(ExtraProjects));
}
}
public List<string> VisualStudioSupportedVersions => EnvironmentValues.VisualStudioVersions;
public List<string> OsBitsTypes => EnvironmentValues.OsBits;
}
}
Child VM xaml
<UserControl x:Class="RemoteDebugger.App.Views.ProjectEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModels="clr-namespace:RemoteDebugger.App.ViewModels"
xmlns:local="clr-namespace:RemoteDebugger.App.Views"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance viewModels:ProjectViewModel}"
>
<Grid>
<Grid.RowDefinitions>
...
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
...
</Grid.ColumnDefinitions>
<ComboBox Grid.Row ="1" Grid.Column="1" ItemsSource="{Binding ProjectTypes}" VerticalAlignment="Center" SelectedItem="{Binding ProjectType,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" FontSize="14" />
<TextBlock Grid.Row ="1" Grid.Column="0" Text="Project type" TextWrapping="Wrap"/>
<TextBlock Grid.Row ="5" Grid.Column="0" Text="Local project path" VerticalAlignment="Center" TextWrapping="Wrap"/>
<TextBox Grid.Row ="5" Grid.Column="1" Height="30" Text="{Binding LocalDllDirRoot,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row ="7" Grid.Column="0" Text="Remote project path" VerticalAlignment="Center" TextWrapping="Wrap"/>
<TextBox Grid.Row ="7" Grid.Column="1" Height="30" Text="{Binding RemoteDllDirRoot,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row ="9" Grid.Column="0" Text="Arguments" VerticalAlignment="Center" TextWrapping="Wrap"/>
<TextBox Grid.Row ="9" Grid.Column="1" Height="30" Text="{Binding Arguments,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row ="3" Grid.Column="0" Text="Executable name" VerticalAlignment="Center" TextWrapping="Wrap"/>
<TextBox Grid.Row ="3" Grid.Column="1" Height="30" Text="{Binding ExecutableName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
</Grid>
Child VM cs file
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using IntelGenericUIFramework.Common;
using RemoteDebugger.Model.DataStructures;
namespace RemoteDebugger.App.ViewModels
{
public class ProjectViewModel : BaseViewModel,ICloneable
{
private ProjectDescriptor _project;
public ProjectViewModel()
{
_project = new ProjectDescriptor();
}
public ProjectViewModel(ProjectDescriptor projectDescriptor)
{
_project = projectDescriptor == null ? new ProjectDescriptor() :
(ProjectDescriptor)projectDescriptor.Clone() ;
UpdateProperties();
}
private void UpdateProperties()
{
foreach (var prop in this.GetType().GetProperties())
{
RaisePropertyChanged(nameof(prop.Name));
}
}
#region Main project values
public string LocalDllDirRoot
{
get => _project.LocalDllDirRoot;
set
{
Project.LocalDllDirRoot = value;
RaisePropertyChanged(nameof(LocalDllDirRoot));
RaisePropertyChanged(nameof(Project));
}
}
public string RemoteDllDirRoot
{
get => _project.RemoteDllDirRoot;
set
{
_project.RemoteDllDirRoot = value;
RaisePropertyChanged(nameof(RemoteDllDirRoot));
RaisePropertyChanged(nameof(Project));
}
}
public string ExecutableName
{
get => Project.ExecutableName;
set
{
_project.ExecutableName = value;
RaisePropertyChanged(nameof(ExecutableName));
RaisePropertyChanged(nameof(Project));
}
}
public string Arguments
{
get => Project.Arguments;
set
{
_project.Arguments = value;
RaisePropertyChanged(nameof(Arguments));
RaisePropertyChanged(nameof(Project));
}
}
public bool IsService
{
get => Project.IsService;
set
{
_project.IsService = value;
RaisePropertyChanged(nameof(IsService));
RaisePropertyChanged(nameof(Project));
}
}
public ProjectType ProjectType
{
get => Project.ProjectType;
set
{
_project.ProjectType = value;
RaisePropertyChanged(nameof(ProjectType));
RaisePropertyChanged(nameof(Project));
}
}
#endregion
public void Clear()
{
LocalDllDirRoot = string.Empty;
RemoteDllDirRoot = string.Empty;
ExecutableName = string.Empty;
IsService = false;
Arguments = string.Empty;
ProjectType = ProjectType.None;
}
public ProjectDescriptor Project
{
get => _project;
set
{
if (value == null)
return;
_project = (ProjectDescriptor)value.Clone();
UpdateProperties();
}
}
public object Clone()
{
return Project.Clone();
}
public List<string> ProjectTypes => Enum.GetNames(typeof(ProjectType)).ToList();
}
}
Example of the broken binding
the marked field not loading the correct selected enum value and show a blank selection, while the other properties are shown as expected.
The problem is that 'ProjectType' property in Child VM cs file not renders on startup in UI in Parent VM xaml
Thanks ahead!
ProjectTypes
is a List<string>
and ProjectType
is a ProjectType
.
The types should match so either change the type of the source collection:
public List<ProjectType> ProjectTypes =>
Enum.GetValues(typeof(ProjectType)).OfType<ProjectType>().ToList();
...or the type of the SelectedItem
source property to string
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.