如何在MAUI应用程序中正确设置XAML绑定

kqhtkvqz  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(120)

我写了一个简单的字典应用程序,只有一个XAML页面,然后我决定把条目和翻译放在单独的视图中,并有自己的ViewmModel,有趣的事情开始了。
基本上,我设法使一切工作,但它只是显示我这些唠叨XAML绑定错误,我不知道为什么,人工智能去愚蠢的这一点,将非常感谢帮助!
EntryModel具有属性HeaderSubheader
TranslationModel有自己的属性
错误看起来像这样:

Severity    Count   Data Context    Binding Path    Target  Target Type Description File    Line    Project

Error   50  EntryViewModel  Header  Label.Text  String  'Header' property not found on 'dosham.ViewModels.EntryViewModel', target property: 'Microsoft.Maui.Controls.Label.Text'    C:\Users\x.dr\source\repos\movsar\chldr\src\chldr_maui\Views\EntryView.xaml 11  dosham

Error   50  EntryViewModel  Subheader   Label.Text  String  'Subheader' property not found on 'dosham.ViewModels.EntryViewModel', target property: 'Microsoft.Maui.Controls.Label.Text' C:\Users\x.dr\source\repos\movsar\chldr\src\chldr_maui\Views\EntryView.xaml 14  dosham

Error   50  EntryViewModel  Translations    StackLayout.ItemsSource IEnumerable 'Translations' property not found on 'dosham.ViewModels.EntryViewModel', target property: 'Microsoft.Maui.Controls.StackLayout.ItemsSource' C:\Users\x.dr\source\repos\movsar\chldr\src\chldr_maui\Views\EntryView.xaml 18  dosham

Error   50  EntryViewModel  .   EntryView.Entry EntryModel  'dosham.ViewModels.EntryViewModel' cannot be converted to type 'chldr_data.DatabaseObjects.Models.EntryModel'   C:\Users\x.dr\source\repos\movsar\chldr\src\chldr_maui\Pages\MainPage.xaml  24  dosham

字符串
我看到它说在我的ViewModel上找不到Header和Subheader,但它不应该在ViewModel上寻找它们,而是在ViewModel的Entry和Translation模型上。我如何在不破坏当前正在工作的绑定的情况下告诉它?
另外,如果你对代码组织有更好的建议,欢迎你提出建议。
代码如下:

首页

--浏览

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:vm="clr-namespace:dosham.ViewModels"
             xmlns:views="clr-namespace:dosham.Views"
             x:Class="dosham.Pages.MainPage">

    <Grid Padding="10">
        <!-- Define the rows -->
        <Grid.RowDefinitions>
            <!-- For CollectionView, takes remaining space -->
            <RowDefinition Height="*"/>
            <!-- For Search Box -->
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <!-- Collection View for Entries -->
        <CollectionView x:Name="EntriesCollectionView" Grid.Row="0"
                        ItemsSource="{Binding FilteredEntries}">
            <CollectionView.ItemTemplate>
                <DataTemplate>

                    <views:EntryView Entry="{Binding .}"></views:EntryView>
                    
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

        <!-- Search Box -->
        <Entry x:Name="SearchBox" Grid.Row="1"
         Text="{Binding SearchText, Mode=TwoWay}" 
         Placeholder="Начните писать..." 
         Margin="0,0,0,10" />
    </Grid>
</ContentPage>


-- Codebehind

public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            BindingContext = App.Services.GetRequiredService<MainPageViewModel>();
        }
    }


-- ViewModel

public class MainPageViewModel : ReactiveObject
{
    public IEnumerable<EntryModel> FilteredEntries
    {
        get => _filteredEntries;
        set => this.RaiseAndSetIfChanged(ref _filteredEntries, value);
    }
....

入口视图

--浏览

<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:views="clr-namespace:dosham.Views"
             x:Class="dosham.Views.EntryView">
    
    <StackLayout Orientation="Vertical">
        <Frame CornerRadius="10" Margin="5" Padding="10" BorderColor="#CACCaa" BackgroundColor="#f9F9F9">
            <StackLayout Orientation="Vertical" Spacing="5">
                <!-- Entry Content -->
                <Label Text="{Binding Header}" FontSize="Medium" FontAttributes="Bold" TextColor="#000" />

                <!-- Source Name -->
                <Label Text="{Binding Subheader}" FontSize="Micro" TextColor="#cba" />

                <!-- Translation views -->
                <StackLayout BindableLayout.ItemsSource="{Binding Translations}">
                    <BindableLayout.ItemTemplate>
                        <DataTemplate>
                            <views:TranslationView Translation="{Binding .}" />
                        </DataTemplate>
                    </BindableLayout.ItemTemplate>
                </StackLayout>
            </StackLayout>
        </Frame>
    </StackLayout>

</ContentView>


-- Codebehind

public partial class EntryView : ContentView
{
    private EntryViewModel _viewModel;

    public static readonly BindableProperty EntryProperty =
         BindableProperty.Create(nameof(_viewModel.Entry), typeof(EntryModel), typeof(EntryView));

    public EntryView()
    {
        _viewModel = App.Services.GetRequiredService<EntryViewModel>();
        BindingContext = _viewModel;
        InitializeComponent();
    }
}


-- ViewModel

public class EntryViewModel : ViewModelBase
 {
     #region Properties, Actions and Constructors
     public EntryModel Entry { get; set; }
     ...
 }

TranslationView

--浏览

<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:dosham.Views"
             x:Class="dosham.Views.TranslationView">

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

        <!-- Language Code Label -->
        <Label Grid.Column="0"
                  Text="{Binding LanguageCode, StringFormat='{0}:'}" 
                  FontSize="Small" 
                  FontAttributes="Italic" 
                  TextColor="#AA6666" />

        <!-- Content Label -->
        <Label Grid.Column="1"
                  Text="{Binding Content, StringFormat=' {0}'}" 
                  FontSize="Small" 
                  TextColor="#666666" />
    </Grid>

</ContentView>


-- Codebehind

public partial class TranslationView : ContentView
{
    private readonly TranslationViewModel _viewModel;

    public static readonly BindableProperty TranslationProperty =
     BindableProperty.Create(nameof(_viewModel.Translation), typeof(TranslationModel), typeof(TranslationView));

    public TranslationView()
    {
        _viewModel = App.Services.GetRequiredService<TranslationViewModel>();
        BindingContext = _viewModel;

        InitializeComponent();
    }
}


-- ViewModel

public class TranslationViewModel : ViewModelBase
{
    public TranslationViewModel(ContentStore contentStore, UserStore userStore) : base(contentStore, userStore)
    { }
    public TranslationModel Translation { get; set; }
....
}


这是视觉效果:x1c 0d1x

5rgfhyps

5rgfhyps1#

经过两周的痛苦和挫折,我最终得到了一个天才的解决方案-摆脱了EntryView和TranslationView,将它们转换为DataTemplates以获得更好的性能,然后创建一个单一的视图来容纳整个事情- EntriesView和EntriesViewModel。
我还将ContentView更改为reactive:ReactiveContentView,将ContentPage更改为reactive:ReactiveContentPage。
生成的代码如下所示:

首页

public partial class MainPage : ReactiveContentPage<MainPageViewModel>
{
    public MainPage()
    {
        ViewModel = App.Services.GetRequiredService<MainPageViewModel>();
        InitializeComponent();

        // Reactive bindings
        this.WhenActivated(disposable =>
        {
            this.OneWayBind(ViewModel, vm => vm.FilteredEntries, v => v.entriesView.ViewModel!.Entries);
        });
    }
}

字符串

入口视图

<?xml version="1.0" encoding="utf-8" ?>
<reactive:ReactiveContentView   xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                                xmlns:viewModels ="clr-namespace:dosham.ViewModels"
                                xmlns:reactive="clr-namespace:ReactiveUI.Maui;assembly=ReactiveUI.Maui"
                                xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                                x:TypeArguments="viewModels:EntriesViewModel"
                                x:Class="dosham.Views.EntriesView">

    <CollectionView x:Name="EntriesCollection"
                    ItemTemplate="{StaticResource EntryTemplate}"
                    ItemsSource="{Binding Entries}">
    </CollectionView>

</reactive:ReactiveContentView>

代码隐藏

public partial class EntriesView : ReactiveContentView<EntriesViewModel>
{
    public EntriesView()
    {
        ViewModel = App.Services.GetRequiredService<EntriesViewModel>();
        InitializeComponent();
    }
}

ViewModel(ViewModelBase继承自ReactiveObject

public class EntriesViewModel : ViewModelBase
{
    private IEnumerable<EntryModel> _entries;
    public IEnumerable<EntryModel> Entries
    {
        get => _entries;
        set => this.RaiseAndSetIfChanged(ref _entries, value);
    }
}


工作得很好:)

mf98qq94

mf98qq942#

我相信你需要的是...
第一个月
注意:我现在不在可以测试这个的地方,所以不能验证我的答案的准确性。

相关问题