XAML 将ContentPage的布局分离到多个ContentView

insrf1ej  于 2023-06-19  发布在  其他
关注(0)|答案(1)|浏览(149)

我正在尝试NET MAUI,并达到了我的主页布局变得太长的地步,所以我想将布局拆分为几个控件。我已经使用依赖注入将ViewModel注册为Interface。
问题是,目前看起来我的HomeViewModel没有传递给MyControl,因为我在HomePage中看到了MyControl中指定的任何内容。我想将HomeViewModel从HomePage传递到MyControl。应该如何正确地做?
HomePage.xaml.cs:

public HomePage(IHomeViewModel homeViewModel)
{
    this.InitializeComponent();
    this.BindingContext = homeViewModel;
    this.HomeViewModel = homeViewModel;
}

HomePage.xaml:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.Pages.HomePage"
             xmlns:controls="clr-namespace:MyApp.Controls;assembly=MyApp"
             x:DataType="viewModels:HomeViewModel"
             Title="">

  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="*" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <controls:MyControl Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" BindingContext="{Binding}" />

  </Grid>

</ContentPage>

MyControl.xaml:

<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:viewModels="clr-namespace:MyApp.ViewModels"
             x:DataType="viewModels:HomeViewModel"
             xmlns:models="clr-namespace:MyApp.Models"
             x:Name="this"
             x:Class="MyApp.Controls.MyControl">

  <ContentView.BindingContext>
    <x:Reference Name="this" />
  </ContentView.BindingContext>

  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

      <Frame Opacity="0" BackgroundColor="{Binding ThemeColor}">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="*"/>
          </Grid.RowDefinitions>
          <Label Text="Title" FontSize="14" Grid.Row="0"></Label>
          <ListView ItemsSource="{Binding Data}" Grid.Row="1" SelectedItem="{Binding SelectedItem}">
            <ListView.ItemTemplate>
              <DataTemplate x:DataType="models:DataModel">
                <ViewCell>
                  <Grid Padding="5">
                    <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="*"/>
                      <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Label Grid.Column="0" Text="{Binding Subject}"/>
                    <Label Grid.Column="1" Text="{Binding Number}"/>
                  </Grid>
                </ViewCell>
              </DataTemplate>
            </ListView.ItemTemplate>
          </ListView>
        </Grid>
      </Frame>
  </Grid>

</ContentView>

HomeViewModel.cs:

private ObservableCollection<DataModel> data;
public ObservableCollection<DataModel> Data
{
  get => this.data;
  set
  {
    this.data = value;
    this.OnPropertyChanged();
  }
}

DataModel.cs:

public class DataModel
  {
    public string Subject { get; set; }
    public string Number { get; set; }
  }
lrpiutwd

lrpiutwd1#

删除:

<ContentView.BindingContext>
    <x:Reference Name="this" />
</ContentView.BindingContext>

然后它将从其父级(包含元素)继承BindingContext,即页面。

正确初始化数据

所有DataModel示例必须设置其SubjectNumber,然后才能对XAML可见。
原因:DataModel没有在其属性上实现INotifyPropertyChanged;属性更改不会自动“递归”。
3种可能的修复方法:
修复1:

// Prepare all data BEFORE setting `Data`:
var data = new ObservableCollection<DataModel>();
foreach (...)
{
    var model = new DataModel();

    // Can set Subject and Number here.
    model.Subject = ...;
    model.Number = ...;

    // Because model is not yet visible in `Data`, we can do `data.Add`
    // EITHER before or after setting `Subject` and/or `Number`.
    data.Add(model);

    // Or set them here.
    model.Subject = ...;
    model.Number = ...;
}
// When all data is fully prepared:
Data = data;   // Now XAML sees the prepared data.

或修复2:

// Prepare each model BEFORE adding it to `Data`:
Data = new ObservableCollection<DataModel>();
foreach (...)
{
    var model = new DataModel(){ Subject = ..., Number = ... };
    // IMPORTANT: Subject and Number MUST be set BEFORE `Data.Add(model)`!
    Data.Add(model);
}
// When all data is fully prepared:
Data = data;   // Now XAML sees the prepared data.

或修复3:

class DataModel : ObservableObject
{
    [ObservableProperty]   // Compiler generates public property "Subject", with property change notification.
    private string subject;
    [ObservableProperty]   // Compiler generate "Number" ...
    private string number;
}

相关问题