我有以下应用程序结构:
浏览次数:
查看模型:
主窗口:
<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 中的数据进行更新?
在这种情况下,您将需要处理 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
属性的变化,并在变化时调整列。