我如何解决在我的 .Net MAUI 页面中出现的奇怪错误?

huangapple go评论77阅读模式
英文:

How do i solve this strange error in my .Net MAUI page?

问题

尝试学习MAUI时,我准备了一个页面,其中有一个被隐藏的标签。在某个事件发生时,该标签变为可见。一切都正常工作,但当我将这个标签放入“CollectionView”并尝试将其与数据库中的值绑定时,该标签会出现“在当前上下文中不存在”的错误,如图所示。我犯了什么错误?谢谢!

错误图片如下:
我如何解决在我的 .Net MAUI 页面中出现的奇怪错误?

带有CollectionView的XAML页面如下:
我如何解决在我的 .Net MAUI 页面中出现的奇怪错误?

英文:

Trying to learn MAUI i prepare a page where there is a Label that is hidden. At a certain event the label becomes visible. All it works ok, but when i put this label inside a "CollectionView" trying to bind her with a value from a database the Label become "not existing in the current context" with the error shown in this picture. Where is the error that i made? Thanks!
我如何解决在我的 .Net MAUI 页面中出现的奇怪错误?

The XAML Page with the CollectionView is this :
我如何解决在我的 .Net MAUI 页面中出现的奇怪错误?

答案1

得分: 0

是的,您不能在模板中使用 x:Name 引用项目。您可以使用数据绑定从您的 ViewModel 控制模板化的 UI 元素,就像 Jason 所说的那样。

根据您的代码,我创建了一个演示并实现了这个功能。

您可以参考以下代码:

  1. 尝试为您的 Item 模型添加一个新属性 IsVisible,并将其绑定到您的 Label Matricola。同时,您还需要为您的 Item 实现 INotifyPropertyChanged 接口,如果更改项目的属性 IsVisible 的值,UI 将自动刷新。
public class Item : INotifyPropertyChanged
{
    public int Id { get; set; }
    public int Value { get; set; }
    public string Matricola { get; set; }

    // 添加属性 IsVisible
    private bool _isVisible;
    public bool IsVisible
    {
        set { SetProperty(ref _isVisible, value); }
        get { return _isVisible; }
    }

    bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;
        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
  1. 创建 ViewModel (TestViewModel.cs)
public class TestViewModel : BaseViewModel
{
    // 在此 ViewModel 中添加其他代码

    public ObservableCollection<Item> Items { get; private set; }

    public TestViewModel()
    {
        Items = new ObservableCollection<Item>();

        Items.Add(new Item { Id = 01, Value = 10, Matricola = "test1" });
        Items.Add(new Item { Id = 02, Value = 13, Matricola = "test2" });
        Items Add(new Item { Id = 03, Value = 16, Matricola = "test3" });
    }
}
  1. 使用示例:

TestPage.xaml

<?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"
             x:Class="MauiContentViewApp.TestPage"
             xmlns:MauiContentViewApp="clr-namespace:MauiContentViewApp;assembly=MauiContentViewApp"
             Title="TestPage">
    <VerticalStackLayout>
        <CollectionView ItemsSource="{Binding Items}">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid Padding="10">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>

                        <Entry Grid.Column="0"
                               BackgroundColor="Yellow"
                               Text="{Binding Value}"
                               Completed="Entry_Completed"
                               VerticalOptions="Center"
                               FontAttributes="Bold" />
                        <Label Grid.Row="1"
                               Grid.Column="1"
                               Text="{Binding Matricola}"
                               IsVisible="{Binding IsVisible}"
                               FontAttributes="Italic"
                               VerticalOptions="Center" />
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </VerticalStackLayout>
</ContentPage>

TestPage.xaml.cs

public partial class TestPage : ContentPage
{
    public TestPage()
    {
        InitializeComponent();

        BindingContext = new TestViewModel();
    }

    private void Entry_Completed(object sender, EventArgs e)
    {
        // 在这里,我们可以获取编辑后的对象并更改此项目的属性 `IsVisible` 的值,然后 `Matri` Label 的 `IsVisible` 将被更新。
        Item item = (Item)((Entry)sender).BindingContext;

        if (item != null && !item.IsVisible)
        {
            item.IsVisible = true;
        }
    }
}

我已经提供了翻译好的部分,如果您需要更多帮助,请告诉我。

英文:

Yes,you cannot reference item inside a template by x:Name. You can use data binding to control templated UI elements from your ViewModel, just as Jason said.

Based on your code, I created a demo and achieved this function.

You can refer to the following code:

1.try to add a new property IsVisible to your Item model, and bind it to your Label Matr. And you also need to implement interface INotifyPropertyChanged for your Item, if you change the value of item's property IsVisible, the UI will refresh automatically.

public class Item: INotifyPropertyChanged 
{
    public int Id { get; set; }    

    public int  Value { get; set; }

    public string Matricola { get; set; }

     // add property IsVisible
    private bool _isVisible;
    public bool IsVisible
    {
        set { SetProperty(ref _isVisible, value); }
        get { return _isVisible; }
    }

    bool SetProperty&lt;T&gt;(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;
        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

2.create viewmodel (TestViewModel.cs)

public class TestViewModel:BaseViewModel 
{
    //add other code in this ViewModel

    public ObservableCollection&lt;Item&gt; Items { get; private set; }

    public TestViewModel() {

        Items = new ObservableCollection&lt;Item&gt;();   

        Items.Add(new Item { Id = 01, Value = 10, Matricola = &quot;test1&quot;});
        Items.Add(new Item { Id = 02, Value = 13, Matricola = &quot;test2&quot; });
        Items.Add(new Item { Id = 03, Value = 16, Matricola = &quot;test3&quot; });

    }

3.Usage example:

TestPage.xaml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt; 
&lt;ContentPage xmlns=&quot;http://schemas.microsoft.com/dotnet/2021/maui&quot;
             xmlns:x=&quot;http://schemas.microsoft.com/winfx/2009/xaml&quot;
             x:Class=&quot;MauiContentViewApp.TestPage&quot;
             xmlns:MauiContentViewApp=&quot;clr-namespace:MauiContentViewApp;assembly=MauiContentViewApp&quot;
             Title=&quot;TestPage&quot;&gt;
    &lt;VerticalStackLayout&gt;
        &lt;CollectionView ItemsSource=&quot;{Binding Items}&quot;&gt;
            &lt;CollectionView.ItemTemplate&gt;
                &lt;DataTemplate&gt;
                    &lt;Grid Padding=&quot;10&quot;&gt;
                        &lt;Grid.RowDefinitions&gt;
                            &lt;RowDefinition Height=&quot;Auto&quot; /&gt;
                        &lt;/Grid.RowDefinitions&gt;
                        &lt;Grid.ColumnDefinitions&gt;
                            &lt;ColumnDefinition Width=&quot;*&quot; /&gt;
                            &lt;ColumnDefinition Width=&quot;*&quot; /&gt;
                        &lt;/Grid.ColumnDefinitions&gt;

                        &lt;Entry Grid.Column=&quot;0&quot; 
                               BackgroundColor=&quot;Yellow&quot;
                               Text=&quot;{Binding Value}&quot; 
                               
                               Completed=&quot;Entry_Completed&quot;  
                               VerticalOptions=&quot;Center&quot; 
                               FontAttributes=&quot;Bold&quot; /&gt;
                        &lt;Label Grid.Row=&quot;1&quot;
                               Grid.Column=&quot;1&quot; 
                               Text=&quot;{Binding Matricola}&quot;
                               
                               IsVisible=&quot;{Binding IsVisible}&quot;
                               FontAttributes=&quot;Italic&quot; 
                               VerticalOptions=&quot;Center&quot; /&gt;
                    &lt;/Grid&gt;
                &lt;/DataTemplate&gt;
            &lt;/CollectionView.ItemTemplate&gt;
        &lt;/CollectionView&gt;
    &lt;/VerticalStackLayout&gt;
&lt;/ContentPage&gt;

TestPage.xaml.cs

public partial class TestPage : ContentPage 
{
      public TestPage()
      {
            InitializeComponent();

            BindingContext = new TestViewModel();
      }

    private void Entry_Completed(object sender, EventArgs e)
    {// here we can get the edited object and change the value of property `IsVisible` of this item ,then the `IsVisible` of `Matri` Label will be updated.
            Item item = (Item)((Entry)sender).BindingContext;

            if (item!=null &amp;&amp; !item.IsVisible) {
            item.IsVisible= true;
        }
    }
}

huangapple
  • 本文由 发表于 2023年3月3日 23:48:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75629192.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定