Как я могу обновить модель представления асинхронно в WPF? - PullRequest
0 голосов
/ 11 ноября 2019

Итак, у меня есть приложение WPF, которое запускается с MainWindow.xaml, а затем запускает фоновый поток, который циклически просматривает страницы для MainWindow. Что действительно делает нить, так это устанавливает контент на новую страницу каждые 20/30 секунд (если есть лучший способ сделать это, тогда я с удовольствием рекомендую это предложение). Итак, я построил приложение, используя шаблон MVVM, чтобы каждая страница имела свой собственный класс viewmodel с соответствующими данными. Каждый класс представляет собой несколько списков, содержащих данные для отображения в таблице Datagrid, и таблица привязана к списку. Но я хочу обновить список без зависания пользовательского интерфейса, по сути, асинхронно или в другом потоке. Как мне это сделать?

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

Пример модели представления

private List<ChangeInfo> nonApprovedChanges;

public ÄrendenStatsViewModel()
{
    nonApprovedChanges = new List<ChangeInfo>;
}

public List<ChangeInfo> NonApprovedChanges //this is bound to a datagrid
{
    get { return nonApprovedChanges; }
    set
    {
        if (nonApprovedChanges != value)
        {
            nonApprovedChanges = value;
            OnPropertyChange();
        }
    }
}

Тема, которая изменяет слайды

private void ManageSlides()
{
    new Thread(() =>
    {
        var page1 = new ExamplePage();
        var page2 = new ExamplePage2();

        while (true)
        {
            Dispatcher.Invoke(new Action(() =>
            {
                Content = page1;
            }));
            Thread.Sleep(1000 * 20);
            Dispatcher.Invoke(new Action(() =>
            {
                Content = page2;
            }
            Thread.Sleep(1000 * 30);
        }
    }).Start();
}

XAML

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Width="*" />
        <RowDefinition Width="15*" />
    </Grid.RowDefinitions>

    <Grid Grid.Row="0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <TextBlock Style="{StaticResource DataGridTitleStyle}" Grid.Column="0" HorizontalAlignment="Left" Text="Not approved" />
        <TextBlock Style="{StaticResource DataGridTitleStyle}" Grid.Column="1" HorizontalAlignment="Right" Text="{Binding NonApprovedChangesCount}" />
    </Grid>

    <DataGrid x:Name="nonApprovedChangesDataGrid" ItemsSource="{Binding NonApprovedChanges}" Style="{StaticResource DataGridStyle}" />
        <DataGrid.Columns>
            <DataGridTextColumn Width="3*" HeaderStyle="{StaticResource DataGridHeaderStyle}" Header="Change" Binding="{Binding Changenumber}" />
            <DataGridTextColumn Width="4*" HeaderStyle="{StaticResource DataGridHeaderStyle}" Header="Requester" Binding="{Binding Requester}" />
            <DataGridTextColumn Width="6*" HeaderStyle="{StaticResource DataGridHeaderStyle}" Header="Date" Binding="{Binding Date}" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

Мне бы хотелось иметь отдельный поток (аналогично слайдеру страниц), который постоянно обновляет список nonApprovedChanges в примере модели представления. Хотя это не обязательно должен быть отдельный поток, я просто хочу использовать нишевой способ обновления списка без зависания интерфейса.

1 Ответ

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

Здесь я использую задачу и Task.Delay для имитации сна.

public partial class MainWindow : Window
{
    // this is a VM
    public object ViewModel { get; set; }

    public MainWindow()
    {
        InitializeComponent();

        Task.Run(async () =>
        {
            // simple DELAY in EXECUTING A CODE
            await Task.Delay(1000);

            // set new VM
            ViewModel = null;

            // updatelayout refreshing a view
            UpdateLayout();
        });
    }
...