【问题标题】:Why isnt my ObservableCollection updating my UI?为什么我的 ObservableCollection 没有更新我的 UI?
【发布时间】:2018-05-18 05:04:13
【问题描述】:

我很确定我错过了一些非常小的东西,但我这辈子都无法弄清楚我哪里出错了。

我正在尝试将我的数据网格绑定到实际上正在获取输入的 ConsoleLines 属性,我对其进行了调试,并且 ConsoleLines 包含多个字符串。 但由于某种原因,它没有更新 UI 并将线条添加到 gridview.. 或者从技术上讲是 TextBlock。

所以我有这样的 MainWindows 设置

public partial class MainWindow : Window
    {
        Server Server = new Server();
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MasterViewModel();
        }

        private void BtnStart_OnClick(object sender, RoutedEventArgs e)
        {
            Server.StartServer();
        }
    }

如您所见,我将 DataContext 设置为 MasterViewModel 的新实例,如下所示

public class MasterViewModel
    {
        public Server Server { get; }
            = new Server();
    }

这是我的服务器类

public class Server : INotifyPropertyChanged
    {
        public Process pServer;
        public Server()
        {

        }

        public ObservableCollection<string> ConsoleLines { get; }
            = new ObservableCollection<string>();

        public void StartServer()
        {
            pServer = new Process();

            pServer.StartInfo.FileName = "java";
            pServer.StartInfo.Arguments = @"-jar " + "-Xms512M -Xmx1G spigot.jar";
            pServer.StartInfo.UseShellExecute = false;
            pServer.StartInfo.RedirectStandardOutput = true;
            pServer.StartInfo.RedirectStandardError = true;
            pServer.StartInfo.RedirectStandardInput = true;

            pServer.OutputDataReceived += OKDataReceived;
            pServer.ErrorDataReceived += ErrorDataReceived;

            pServer.Start();

            pServer.BeginErrorReadLine();
            pServer.BeginOutputReadLine();
        }

        private void ErrorDataReceived(object sender, DataReceivedEventArgs e)
            => Application.Current.Dispatcher.Invoke(() => ConsoleLines.Add($"ERROR: {e.Data}"));

        private void OKDataReceived(object sender, DataReceivedEventArgs e)
            => Application.Current.Dispatcher.Invoke(() => ConsoleLines.Add($"MESSAGE: {e.Data}"));

        public event PropertyChangedEventHandler PropertyChanged;
        [NotifyPropertyChangedInvocator]
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

据我所知,一切都设置正确,我看不出有什么问题。

这是我的 XAML

<DataGrid ItemsSource="{Binding Server.ConsoleLines}" Width="400" Margin="182,109,210,68">
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding}"></TextBlock>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
        <Button Name="BtnStart" Click="BtnStart_OnClick" Content="Start Server" HorizontalAlignment="Left" Margin="365,388,0,0" VerticalAlignment="Top" Width="75"/>

编辑 初始化服务器的新实例,然后使用 Button 在新实例上启动方法似乎是问题。我不知道为什么。

【问题讨论】:

  • 你应该在 ConsoleLines 的集合上使用 OnPropertyChanged
  • 您绑定到错误的服务器实例。 VM 中有一个,View 中有另一个,您在 View 中启动一个,但 UI 绑定到 VM 中的那个
  • @SirRufo 问题是当我创建一个新的服务器实例并尝试使用我的按钮启动它时,它运行但没有绑定在那里
  • Ehm,当你有 2 辆车(蓝色和红色)并且你启动红色的那辆时,蓝色的也启动了吗?当你需要蓝色的运行时,然后启动蓝色的

标签: c# .net wpf mvvm data-binding


【解决方案1】:

您应该从 MainWindow 中删除 Server 字段并启动 DataContext 中的服务器。

private void BtnStart_OnClick(object sender, RoutedEventArgs e)
{
    ((MasterViewModel)DataContext).Server.StartServer();
}

或者,像这样初始化视图模型:

DataContext = new MasterViewModel { Server = Server };

将 Server 字段值分配给视图模型中的 Server 属性(然后必须是读/写的)。否则你有两个服务器实例。

【讨论】:

    猜你喜欢
    • 2018-03-13
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-21
    • 2011-10-10
    相关资源
    最近更新 更多