Моя статическая модель/свойство не привязана к моему пользовательскому интерфейсу

Новое в WPF.

Я пытаюсь привязать свою модель к своему пользовательскому интерфейсу. Поэтому, когда свойство изменяется во время моих действий пользователя, я хочу, чтобы поле обновлялось, независимо от того, происходит ли оно на моем пользовательском интерфейсе.

Это моя модель:

namespace WpfApplication1
{
    public class model2
    {
        private static string myField2;

        public static string MyField2
        {

            get { return myField2; }
            set { myField2 = value; }
        }
    }
}

Моя разметка:

<Window x:Class="WpfApplication1.MainWindow"     
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"       
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:model2 x:Key="mymodel"/>
    </Window.Resources>
    <Grid>
        <StackPanel Orientation="Vertical">
            <TextBlock Text="{Binding Source={StaticResource ResourceKey=mymodel}, Path=MyField2}"></TextBlock>     
            <Button Content="static test!" Click="Button_Click_1" />
        </StackPanel>
    </Grid>
</Window>

Мой код:

using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            model2.MyField2 = "static!";
        }
    }
}

Поле в пользовательском интерфейсе не изменяется?

Ответ 1

Вам необходимо уведомить об изменениях в пользовательском интерфейсе, чтобы он мог обновляться новыми значениями.

В вашем случае вы хотите уведомить статические свойства изменений, чтобы вам понадобилось статическое событие. Проблема заключается в том, что для интерфейса INotifyPropertyChanged требуется событие участника, поэтому вы не сможете этого сделать.

Лучший снимок - реализовать шаблон Singleton:

namespace WpfApplication1
{
    public class model2 : INotifyPropertyChanged
    {
        //private ctor so you need to use the Instance prop
        private model2() {}

        private string myField2;

        public string MyField2
        {

            get { return myField2; }
            set { 
                myField2 = value; 
                OnPropertyChanged("MyField2");
            }
        }

        private static model2 _instance;

        public static model2 Instance {
            get {return _instance ?? (_instance = new model2();)}
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName) {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

И затем создайте свойство свойство member и привяжите его следующим образом:

<Window x:Class="WpfApplication1.MainWindow"     
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication1"       
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:model2 x:Key="mymodel"/>
    </Window.Resources>
    <Grid>
        <StackPanel Orientation="Vertical">
            <TextBlock Text="{Binding Source={x:Static local:model2.Instance}, Path=MyField2}"/>  
            <Button Content="static test!" Click="Button_Click_1" />
        </StackPanel>
    </Grid>
</Window>

Код позади:

using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            model2.Instance.MyField2 = "static!";
        }
    }
}

Ответ 2

Используйте расширение Static для привязки текстового свойства TextBlocks:

<TextBlock Text="{Binding Source={Static MyModel.MyField2}, Mode=TwoWay">

Но все же свойство должно поднять событие PropertyChanged. Мое понимание, почему вы используете статическое поле, - это возможность установить значение из другого места. Вместо этого вы должны использовать сообщения? Оформить заказ инструментария MVVM Light и посланника. Это отделит две компоненты

Ответ 3

Я думаю, что статические свойства не то, что вы хотите использовать, из комментариев, которые я могу сделать, вы используете только для того, чтобы ваша программа работала. Ниже приведен полный рабочий код.

App.xaml

Удалите код StartupUri="MainWindow.xaml, вместо этого мы создадим MainWindow в коде, чтобы предоставить DataContext.

App.xaml.cs

Здесь мы присваиваем объект Model2 как Window.DataContext и затем показываем окно.

public partial class App : Application
    {
        public App()
        {
            Model2 model = new Model2();
            MainWindow window = new MainWindow();
            window.DataContext = model;
            window.Show();
        }
    }

MainWindow.xaml.cs

   public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            //We get hold of `DataContext` object
            var model = this.DataContext as Model2; 
            model.MyField2 = "Hello World";
        }
    }

Модель:

public class Model2 : INotifyPropertyChanged
    {

        private string _myField2;

        public string MyField2
        {
            get { return _myField2; }
            set
            {
                _myField2 = value;
                OnPropertyChanged("MyField2");
            }
        }

        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

MainWindow.xaml

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel Orientation="Vertical">
            <TextBlock Text="{Binding MyField2}"></TextBlock>
            <Button Content="static test!" Click="ButtonBase_OnClick" />
        </StackPanel>
    </Grid>
</Window>

И я проверил, это работает!