Avalonia DataContext 在后面的代码中为空

问题描述 投票:0回答:1

我有以下应用程序结构:

浏览次数:

  • 主窗口
  • 主视图
  • 查看1
  • 查看2

查看模型:

  • 主视图模型

主窗口:

<Window xmlns="https://github.com/avaloniaui"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="using:Frontend.ViewModels"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:views="clr-namespace:Frontend.Views"
    mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
    x:Class="Frontend.Views.MainWindow"
    Icon="/Assets/avalonia-logo.ico"
    Title="Frontend">

    <views:MainView/>
</Window>

主视图:

<UserControl xmlns="https://github.com/avaloniaui"
         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:vm="clr-namespace:Frontend.ViewModels"
         xmlns:views="clr-namespace:Frontend.Views"
         mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
         x:Class="Frontend.Views.MainView"
         x:DataType="vm:MainViewModel">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.3*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.4*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
    
        <views:View1 Grid.Row="0" Grid.Column="0"/>
        <views:View2 Grid.Row="1" Grid.Column="1"/>
    
    </Grid>

</UserControl>

视图1:

<UserControl xmlns="https://github.com/avaloniaui"
             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:vm="clr-namespace:Frontend.ViewModels"
             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
             x:Class="Frontend.Views.View1"
             x:DataType="vm:MainViewModel">

    <DataGrid Name="TableDataGrid" AutoGenerateColumns="False" IsReadOnly="True" GridLinesVisibility="All"
              CanUserReorderColumns="True" CanUserResizeColumns="True" CanUserSortColumns="True"
              BorderThickness="1" BorderBrush="Gray" VerticalAlignment="Center" HorizontalAlignment="Center"/>

</UserControl>

在 View1 的代码隐藏中,我想更改 DataGrid,如下所示:

using Avalonia.Controls;
using Avalonia.Data;
using Frontend.ViewModels;
using System.Data;

namespace Frontend.Views;

public partial class View1 : UserControl
{
    public View1()
    {
        InitializeComponent();
        var viewModel = DataContext as MainViewModel;
        TableDataGrid.ItemsSource = viewModel.TableData.DefaultView;

        foreach (DataColumn x in viewModel.TableData.Columns)
        {
            if (x.DataType == typeof(bool))
            {
                TableDataGrid.Columns.Add(new DataGridCheckBoxColumn { Header = x.ColumnName, Binding = new Binding($"Row.ItemArray[{x.Ordinal}]") });
            }
            else
            {
                TableDataGrid.Columns.Add(new DataGridTextColumn { Header = x.ColumnName, Binding = new Binding($"Row.ItemArray[{x.Ordinal}]") });
            }
        }
    }
}

问题在于 DataContext 是

null
。根据 Avalonia 文档,任何控件都将继承其父级的 DataContext,如果它们没有自己的定义。问题似乎是正在创建视图并稍后分配上下文,因为在 View2 中我绑定了
MainViewModel
的属性,并且这些属性工作正常,而无需我设置任何数据上下文。

所以,我的问题是 - 如何使 DataGrid 可以通过代码隐藏使用 DataContext 中的数据进行更新?

c# wpf xaml avaloniaui avalonia
1个回答
0
投票

在这种情况下,您将需要处理 DataContextChanged 和 Initialized 事件。
我正在用手机编写示例代码,因此可能会出现一些小错误。

        public View1()
        {
            DataContextChanged += OnDataContextChanged;

            InitializeComponent();            
        }

        private void OnDataContextChanged(object sender, EventArgs e)
        {
            if (IsInitialized)
            {

                var viewModel = DataContext as MainViewModel;
                TableDataGrid.ItemsSource = viewModel.TableData.DefaultView;

                foreach (DataColumn x in viewModel.TableData.Columns)
                {
                    if (x.DataType == typeof(bool))
                    {
                        TableDataGrid.Columns.Add(new DataGridCheckBoxColumn { Header = x.ColumnName, Binding = new Binding($"Row.ItemArray[{x.Ordinal}]") });
                    }
                    else
                    {
                        TableDataGrid.Columns.Add(new DataGridTextColumn { Header = x.ColumnName, Binding = new Binding($"Row.ItemArray[{x.Ordinal}]") });
                    }
                }
            }
            else
            {
                Initialized += delegate { OnDataContextChanged(sender, e); };
            }
        }

但我建议您监听

DataGrid.ItemsSource
属性的变化,并在变化时调整列。

© www.soinside.com 2019 - 2024. All rights reserved.