Чего не хватает для обновления этого текстового поля с привязкой к данным? Почему он обновляется, если я использую прерыватель MessageBox? - PullRequest
0 голосов
/ 11 января 2019

Я создал проект WPF под названием WpfDataBindTests. С MainWindow.xaml у меня есть эта настройка:

<Window x:Class="WpfDataBindTests.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:WpfDataBindTests"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid Name="myGrid">
        <TextBox Text="{Binding Path=Name2}"/>
    </Grid>
</Window>

В .xaml.xs я получил это

namespace WpfDataBindTests
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            myGrid.DataContext = this;
            _name2 = "Start...";
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private string _name2;

        public string Name2
        {
            get { return _name2; }
            set
            {
                if (value != _name2)
                {
                    _name2 = value;
                    OnPropertyChanged("Name2");
                }
            }
        }
    }
}

Затем я изменил тип приложения на консольное и удалил App.xaml, чтобы переопределить класс Program в качестве точки входа:

namespace WpfDataBindTests
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            MainWindow x = new MainWindow();
            x.Show();
            x.Name2 = "HELLO";
            System.Threading.Thread.Sleep(1000);
            x.Name2 = "THIS";
            System.Threading.Thread.Sleep(1000);
            x.Name2 = "WORKED";
            Console.ReadKey();
        }
    }
}

Моя проблема в том, что вызов строк x.Name2 = "xyz" не меняет текст, отображаемый в окне WPF.

До сих пор я пытался добавить в параметр привязки TextBox: RelativeSource={RelativeSource AncestorType=Window} а также Mode=TwoWay, ни один из которых не имеет значения.

Но если я добавлю MessageBox.Show ("") между строками x.Name2 = "", текст в форме изменится !!! - Итак, что здесь происходит, что вызывает обновление

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        MainWindow x = new MainWindow();
        x.Show();
        x.Name2 = "HELLO";
        MessageBox.Show("");
        System.Threading.Thread.Sleep(1000);
        x.Name2 = "THIS";
        MessageBox.Show("");
        System.Threading.Thread.Sleep(1000);
        x.Name2 = "WORKED";
        MessageBox.Show("");
        Console.ReadKey();
    }
}

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Я нашел решение для своей проблемы, я избавился от DataBinding и просто назвал мой TextBox как "TBox", хотя я не думаю, что эта часть была необходима, но я удалил все в MainWindow, включая INotifyPropertyChanged

Так что мой MainWindow.xaml.cs теперь выглядит так, и он работает отлично и денди:

    private delegate void NoArgDelegate();

    private static void Refresh(DependencyObject obj)

    {
        obj.Dispatcher.Invoke(DispatcherPriority.ApplicationIdle,
            (NoArgDelegate)delegate { });
    }

    public void LogoUpdate(MainWindow w, string m)
    {
        w.TBox.Text = m;
        Refresh(w);
    }
0 голосов
/ 11 января 2019

Затем я изменил тип приложения на консольное и удалил App.xaml, чтобы переопределить класс Program в качестве точки входа.

Почему ты это сделал? Если вы определяете свой собственный Main метод, вы должны создать экземпляр класса Application и вызвать его метод Run. Это присоединяет новый экземпляр Dispatcher к потоку пользовательского интерфейса, а затем вызывается метод Run объекта Dispatcher. Это запускает насос сообщений для обработки сообщений Windows. Это необходимо для просмотра обновлений:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        Application app = new Application();
        app.Run(new MainWindow());
    }
}

Метод Run не вернется, пока вы не закроете приложение.

Если вы используете шаблон WPF Application по умолчанию в Visual Studio и, например, обрабатываете событие Loaded для своего окна, вы должны увидеть, что значение обновляется, например ::

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        myGrid.DataContext = this;
        _name2 = "Start...";

        Loaded += MainWindow_Loaded;
    }

    private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        //wait for 2 seconds...
        await Task.Delay(2000);
        //...and then set the property
        Name2 = "new...";

    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private string _name2;

    public string Name2
    {
        get { return _name2; }
        set
        {
            if (value != _name2)
            {
                _name2 = value;
                OnPropertyChanged("Name2");
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...