【问题标题】:change property of singleton from another singleton?从另一个单例更改单例的属性?
【发布时间】:2022-12-05 15:21:15
【问题描述】:

我正在尝试从 MVVM 下的类“ClassA”更改类“MainViewModel”的属性“MyText”。我不确定我这样做是否正确。 这是我的代码。

<Window.DataContext>
         <local:MainViewModel/>
     </Window.DataContext>
     <Grid>
         <StackPanel Orientation="Vertical">
             <TextBlock Text="{Binding MyText}"
                        Margin="50"/>
             <Button Content="Main Class"
                     Width="150"
                     Height="70"
                     Margin="50"
                     Command="{Binding Cmd}"
                     CommandParameter="MainClass"/>
    
             <Button Content="Class A"
                     Width="150"
                     Height="70"
                     Command="{Binding Cmd}"
                     CommandParameter="ClassA" />
         </StackPanel>
     </Grid>
    public class MainViewModel : BaseViewModel
    {
        private static MainViewModel instance = new MainViewModel();
        static MainViewModel()
        {
            instance = new MainViewModel();
        }
        public static MainViewModel Instance
        {
            get => instance;
        }
        private string myText = string.Empty;
        public string MyText
        {
            get
            {
                return myText;
            }
            set
            {
                if( myText != value)
                {
                    myText = value;
                    OnPropertyChanged();
                }
            }
        }
        public RelayCommand Cmd { get => new RelayCommand(CmdExec); }
        private void CmdExec(object parameter)
        {
            switch (parameter.ToString())
            {
                case "MainClass":
                    try
                    {
                        MyText = "I am from Class -> MainViewModel!";
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                    break;

                case "ClassA":
                    try
                    {
                       // MyText = "I'am from Class -> ClassA!";
                        ClassA.Instance.ChangeText();
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                    break;
                default:
                    break;
            }
        }
    }
    public class ClassA
    {
        private static readonly ClassA instance=new ClassA();

        static ClassA()
        {
           
        }
        private ClassA() { }
        public static ClassA Instance
        {
            get => instance;
        }
        public void ChangeText()
        {
            MainViewModel.Instance.MyText = "I'am from Class -> ClassA!";
        }
    }
    public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
    public class RelayCommand : ICommand
    {
        private readonly Action<object> _execute;
        private readonly Predicate<object> _canExecute;

        public RelayCommand(Action<object> execute)
            : this(execute, null)
        {
        }
        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        public void Execute(object parameter)
        {
            _execute(parameter);
        }
    }

不幸的是,它对我不起作用。这应该是一个简单的调用。有谁知道可能做错了什么?我应该怎么办?

【问题讨论】:

    标签: c# wpf mvvm data-binding singleton


    【解决方案1】:

    因为 DataContext 被设置为 MainViewModel 的另一个实例。

     <Window.DataContext>
         <local:MainViewModel/>
     </Window.DataContext>
    

    你仍然有 MainViewModel 的公共构造函数,所以上面的代码创建了一个新的 MainViewModel 实例。

    您需要拥有 MainViewModel 的私有构造函数,以确保可以创建一个类的唯一一个实例。

    public class MainViewModel : BaseViewModel
    {
        private static MainViewModel instance = new MainViewModel();
        static MainViewModel()
        {
            instance = new MainViewModel();
        }
        private MainViewModel(){}
        public static MainViewModel Instance
        {
            get => instance;
        }
        ...
    }
    

    然后你需要在后面的代码中设置DataContextMainWindow

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = MainViewModel.Instance;
        }
        ...
    }
    

    摆脱

    <Window.DataContext>
         <local:MainViewModel/>
     </Window.DataContext>
    

    【讨论】:

      【解决方案2】:

      我会补充@user2250152的回答。 他提出的在 Code Behind 中获取 Singleton 实例的方法在 Design Mode 中通常非常不方便,因为 Code Behind 不在该模式下执行。 您可以获取 XAML 中的值:

      <Window ---------------
              ---------------
              DataContext="{x:Static local:MainViewModel.Instance}">
      

      附言此外,在您的实现中,实例字段没有意义。
      您必须在第一次调用时使用自动属性或初始化。

          public class SomeClass
          {
              private SomeClass() { }
              public static SomeClass Instance {get;} = new SomeClass();
      
          public class SomeClass
          {
              private static SomeClass? _instance;
              private SomeClass() { }
              public static ClassA Instance => _instance ??= new SomeClass();
      

      【讨论】:

      • 谢谢你补充的内容,让我更明白了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多