и ProjectVarioViewModel выполнить реализацию iProjectViewModel . Первый из каждого получения одного экземпляра своего представления, но следующий из одного типа получит один и тот же экземпляр представления, что и первый.
У меня есть TabControl Показ представлений из ObservableCollection Projects . [code]ProjectViewModel[/code] и ProjectVarioViewModel выполнить реализацию iProjectViewModel . Первый из каждого получения одного экземпляра своего представления, но следующий из одного типа получит один и тот же экземпляр представления, что и первый.[code]
new tri new vario
< /code> viewmodels: < /p> using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows.Input;
namespace MultiTab;
public interface IProjectViewModel : ICloneable { public string ProjectTitle { get; set; } public float Margin { get; set; } }
public class Project : IProjectViewModel { public Project(string name) { ProjectTitle = name; } public float Margin { get; set; } public string ProjectTitle { get; set; } public object Clone() => MemberwiseClone(); }
public class ProjectViewModel : Project { public ProjectViewModel(string name) : base(name) {} }
public class ProjectVarioViewModel : Project { public ProjectVarioViewModel(string name) : base(name) {} }
public enum ProjectType { Triptych, Vario, }
public class MainViewModel : INotifyPropertyChanged { private IProjectViewModel? _selectedProject; private DelegateCommandListen? _newProjectCommand; private ICommand? _closeProjectCommand;
public ObservableCollection Projects { get; protected set; } = new();
public IProjectViewModel? SelectedProject { get => _selectedProject; set => SetField(ref _selectedProject, value); }
public ICommand NewProjectCommand { get { return _newProjectCommand ?? (_newProjectCommand = new DelegateCommandListen( s => { var ptype = _argToProjectType[(string) s]; var name = $"{GetNewProjectTitle()} [{ptype.ToString()}]"; CreateNewProject(name, ptype); }, s => true)); } }
public ICommand CloseProjectCommand => _closeProjectCommand ?? (_closeProjectCommand = new DelegateCommandListen( s => { var closingvm = (IProjectViewModel)s; Projects.Remove(closingvm); }, s => s is not null));
public void CreateNewProject(string projectname, ProjectType ptype) { IProjectViewModel vm; switch (ptype) { case ProjectType.Triptych: vm = new ProjectViewModel(projectname); break; default: case ProjectType.Vario: vm = new ProjectVarioViewModel(projectname); break; }
Projects.Add(vm); SelectedProject = vm; }
#region inpc
public event PropertyChangedEventHandler? PropertyChanged;
protected bool SetField(ref T field, T value, [CallerMemberName] string? propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; }
#endregion } < /code> Теперь просмотры, Pview и TView. < /p> pview: < /p>
< /code> tview: < /p>
< /code> Их код-бродяга одинаково: < /p> using System.Windows.Controls; using System.Xml;
namespace MultiTab { /// /// Interaction logic for TView.xaml /// public partial class TView : UserControl { public TView() { InitializeComponent(); }
public UniqueId NameID { get; } = new(); } } < /code> Утилита DelegateCommandListen: < /p> using System.ComponentModel; using System.Linq.Expressions; using System.Windows.Input;
namespace MultiTab;
/// /// Implementation of ICommand with listening to 1+ properties change (INPC) /// ICommand Zcommand = new DelegateCommandListen { /// ExecuteDelegate = ZExecuteCommand, /// CanExecuteDelegate = CanExecuteZCommand }.ListenOn(this, o => o.INPCpropFromVM);; /// public class DelegateCommandListen : ICommand { private readonly List _controlEvent; private Action _executeDelegate;
/// /// Implementation of ICommand with listening to 1+ properties change (INPC) /// ICommand Zcommand = new DelegateCommandListen { /// ExecuteDelegate = ZExecuteCommand, /// CanExecuteDelegate = CanExecuteZCommand }.ListenOn(this, o => o.INPCpropFromVM);; /// public DelegateCommandListen() { _controlEvent = new List(); }
/// /// Implementation of ICommand with listening to 1+ properties change (INPC) /// ///
/// public DelegateCommandListen(Action executeDelegate, Predicate canExecuteDelegate) { _controlEvent = new List(); ExecuteDelegate = executeDelegate; CanExecuteDelegate = canExecuteDelegate; }
public List PropertiesToListenTo { get; set; }
public Predicate CanExecuteDelegate { get; set; }
public Action ExecuteDelegate { get { return _executeDelegate; } set { _executeDelegate = value; ListenForNotificationFrom((INotifyPropertyChanged)_executeDelegate.Target); } }
public void RaiseCanExecuteChanged() { if (_controlEvent is { Count: > 0 }) _controlEvent.ForEach(ce => { ((EventHandler)ce.Target)?.Invoke(null, EventArgs.Empty); }); }
public DelegateCommandListen ListenOn (TObservedType viewModel, Expression propertyExpression) where TObservedType : INotifyPropertyChanged { var propertyName = GetPropertyName(propertyExpression); viewModel.PropertyChanged += (s, e) => { if (e.PropertyName == propertyName) RaiseCanExecuteChanged(); }; return this; }
public void ListenForNotificationFrom(TObservedType viewModel) where TObservedType : INotifyPropertyChanged { viewModel.PropertyChanged += (s, e) => RaiseCanExecuteChanged(); }
private static string GetPropertyName(Expression expression) where T : INotifyPropertyChanged { var lambda = expression as LambdaExpression; var memberInfo = GetMemberExpression(lambda).Member; return memberInfo.Name; }
private static MemberExpression GetMemberExpression(LambdaExpression lambda) { MemberExpression memberExpression; if (lambda.Body is UnaryExpression body) { var unaryExpression = body; memberExpression = unaryExpression.Operand as MemberExpression; } else memberExpression = lambda.Body as MemberExpression; return memberExpression; }
#region ICommand Members
public bool CanExecute(object parameter) => CanExecuteDelegate == null || CanExecuteDelegate(parameter);