0

i already the project from the official tutorial of .NET MAUI until step 5 using Communitytoolkit.Mvvm: text

Now, instead of binding only a Text (which is a standard type that can be accessed from everywhere) i would like to bind a simple object (called ItemGroup) with two members (bool isChecked and string name).

How to do that? For a global access i made this class in the MainView folder called ItemGroup. This class is not accessable and i don't know how to do that it is. I changed the code in the MainPage.xaml like this:

                <CollectionView ItemsSource="{Binding Items}"
                                Grid.Row="1">
                    <CollectionView.ItemTemplate>
                        <DataTemplate x:DataType="{x:Type x:ViewModel.ItemGroup}">
                            <Grid >
                                <CheckBox IsChecked="{Binding ItemGroup.IsChecked}" Grid.Column="0"/>
                                <Label Text="{Binding ItemGroup.name}"  Padding="10" Grid.Column="1"                                                                  
                                    BackgroundColor="LightGray"/>
                            </Grid>
                        </DataTemplate>
                    </CollectionView.ItemTemplate>
                </CollectionView>

See also the project structure with the ItemGroup class in the ViewModel folder as well as the error message:

enter image description here

where the content page is declared as this:

enter image description here

Remark: The MainViewModel looks like this:

enter image description here

  • Should i declare some uses, or namespace?
  • where in the project should i place the Class of the objects i would bind?

Thanks in advance, Thomas

Also tryed to implement the class ItemGroup in the MainViewModel.cs but then i had any more problems with access to this class.

  • I've answered a similar question [here](https://stackoverflow.com/questions/75095194/binding-property-not-found-on-viewmodel-even-though-it-exists/75095965#75095965) recently, hope that helps. – Gerald Versluis Jan 18 '23 at 11:40
  • 2
    Please do not post code as images – Jason Jan 18 '23 at 11:45

3 Answers3

0

Try this

<Label Text="{Binding name}" …

Note that name must be a public property

Jason
  • 86,222
  • 15
  • 131
  • 146
0

I believe your problem lies with you Binding declaration inside you ItemTemplate. Given that you bound your CollectionView's ItemSource to "items", the ItemTemplate's data context is now a single itemGroup from your list. Therefore, you should not be writing

<CheckBox IsChecked="{Binding ItemGroup.IsChecked}"[...]

But instead

<CheckBox IsChecked="{Binding isChecked}"[...]

Since you are already "within" a single itemgroup object. Same goes for your Label. Furthermore, I don't think you actually need to declare the Datatype for your item's DataTemplate.

p.s. Watch out for your item declaration, it seems like you have both items and Items declared in your ViewModel; and both seem public.

DevenCC
  • 441
  • 4
  • 9
  • Hi, ok i understood to not write ItemGroup.IsChecked, when ItemGroup is already the scope. But that is not the Problem. The Problem comes earlier on the declaration of the Datatype, that he cannot resolve to this Class: "Property "ItemGroup" not found..." And: If I don't declare the Datatype in the DataTemplate i should Bind with ItemGroup.IsChecked - Right? But then he says the same, that he don't know "ItemGroup" at this place in the code... –  Jan 18 '23 at 16:03
  • Try removing the x:DataType declaration as well as the "ItemGroup." prefix. The scope is a single item group not because of the DataType you declared, but because you passed in the itemgroup collection "items" as the ItemSource to your CollectionView. The collection view will iterate through each indivual "itemGroup" from your collection "items" and render them each one with an instance of the ItemTemplate declared. – DevenCC Jan 18 '23 at 17:03
  • Ok, i tryed this out. But now it doesn't know the members. If i understood right. The compiler should know that i have a collection of type ItemGroup's. So he should recognize that??? The actual code: ' ' –  Jan 19 '23 at 10:45
  • Yes, that is correct, everything should be recognized by the compiler at that point. The only other standout thing I see here, is according to your post image, your ItemGroup object has lower case properties. Hence "name" and "isChecked" and not "Name" and "IsChecked". Bindings are case sensitive, so watch out for those. Similarly, you seem to have both "items" and "Items" but I do not see the declaration in your ViewModel of the UpperCase Items, so you might also need to be Binding ItemSource="{Binding items}" – DevenCC Jan 19 '23 at 13:31
  • Also Thomas, I don't know if you are familiar with [Value Converters](https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/data-binding/converters?view=net-maui-7.0) but this could be a great tool for you to use to catch and inspect in real time the values that you are trying to bind to. Adding a dummy converter that just gives back the same value will allow you to put a breakpoint within the converters method. There you can inspect in runtime the bound values you have. It's a very useful trick to achieve some sort of xaml debugging. – DevenCC Jan 19 '23 at 13:55
  • About case sesitivity: the Items Object is right, even you only see the lower case related "items". This is because i use the Communitytoolkit.Mvvm which is changing the related object to Uppercase. But in the case of the properties in the ItemGroup object, this members would be the same, because of the toolkit just returns the ItemGroup-Object in which the properties doesn't change its name. But i alredy tried out both, lower and upper case. About the Value Converters: ok thanks, i'll try this out... –  Jan 19 '23 at 16:01
0

You have a number of issues here.

The community mvvm toolkit includes code generators.

A variable:

[ObservableProperty]    
string text;

Is examined by the code generator at compile time and in a partial class it will add a public property Text.

Binding is case sensitive and you need to bind to public properties so you need to use upper case on that first letter. Binding Text rather than Binding text.

You might have other instances where you did the same sort of thing.

I don't see where you use it but that add [Relaycommand] will generate AddCommand as a public property which you bind to.

Additionally you have misunderstood how an itemscontrol gets an item out a bound collection per row. As DevenCC points out, once you bind ItemsSource to Items then each row will get an instance of whatever is in that collection so you should bind IsChecked rather than ParentProperty.IsChecked.

As to where to put classes. In large apps it is a nuisance to flip between a folder contains views and another contains viewmodels. You might want to consider a folder contains each pair of view and viewmodel. Hence a foo folder containing fooView and fooViewModel

Andy
  • 11,864
  • 2
  • 17
  • 20