admin管理员组文章数量:1421028
I have a really complex page in my .Net Maui App. And I'm getting an issue where when I update certain visual elements in a CollectionView, the changes are applied to the wrong item in the CollectionView. So if I change the icon tint on the view of an item named "Banana",the change is actually applied to an item named "Orange".
I have a grouped CollectionView, that displays a custom control in each item's DataTemplate
it's a view to display MyItem
, a data class that gets synced with a database. As per my reading the custom control doesn't set its own binding context but rather uses bindable properties to get to the data.
(CollectionView's grouping code omitted for clarity)
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="{x:Type model:MyItem}">
<controls:MyCustomControl MyItem="{Binding .}" />
</DataTemplate>
</CollectionView.ItemTemplate>
Now, I have an ObservableProperty on MyItem
that stores a state in an enum. And a IValueConverter to convert that state into a color. I want to to use the Community toolkit tint behaviour to color a white icon based on the state.
<Image Source="circle_icon.png">
<Image.Behaviors>
<toolkit:IconTintColorBehavior TintColor="{Binding Source={x:Reference ThisComponent},
Path=MyItem.State,
Converter={StaticResource StateToColor}}"/>
</Image.Behaviors>
</Image>
<!-- Label for debugging CORRECT STATE SHOWN-->
<Label Text="{Binding Source={x:Reference Component},
Path=MyItem.State}"/>
State is an enum that can be Green, Blue, Red.
The issue I'm having is that when I change the state, the wrong item in the collection view gets tinted. I have a label next to it to debug, and the correct state is always shown, even after updates. So I know it's not an issue with the property notifications or anything like that, since the label has the correct data at all times.
I can use simple triggers to change the TextColor of the label. That works. But for some reason the tinting doesn't work. I can also use the above converter to colonize a box view, and that works properly. So it's something to do with the community toolkit behaviours and other visual changes that I've seen.
I also noticed a very very similar issue when I try to do an animation on part of the control. The wrong item gets animated.
I suspect (and my conversations with AI reinforce this view) that the issue here has to do with recycling. I suspect that some link between the view displaying the current item has been dissociated with the one that was initialized with it. Or some small time delay has changed the contents just after the visual change is applied. It doesn't seem like Maui has any way to disable recycling, even though Xamarin appears to have that functionality. So I can't be sure that's the issue.
I'm using maui v8.0.100 if that makes any difference.
I'm not sure if this is relevant, but when I adjust the state, I actually save the item to a database, and then I shortly thereafter receive an event from the database that something has changed, and it syncs the ObservableCollection. I have it set up so I don't clear and repopulate the items, but update the existing items with the new data.
I don't think it makes sense to post more code here, because it's a really complicated control with tons of stuff going on.
I'm at my wits end and have tried tons of stuff, and can't seem to solve the issue. Hopefully someone can point me in the right direction for how to approach this problem.
I have a really complex page in my .Net Maui App. And I'm getting an issue where when I update certain visual elements in a CollectionView, the changes are applied to the wrong item in the CollectionView. So if I change the icon tint on the view of an item named "Banana",the change is actually applied to an item named "Orange".
I have a grouped CollectionView, that displays a custom control in each item's DataTemplate
it's a view to display MyItem
, a data class that gets synced with a database. As per my reading the custom control doesn't set its own binding context but rather uses bindable properties to get to the data.
(CollectionView's grouping code omitted for clarity)
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="{x:Type model:MyItem}">
<controls:MyCustomControl MyItem="{Binding .}" />
</DataTemplate>
</CollectionView.ItemTemplate>
Now, I have an ObservableProperty on MyItem
that stores a state in an enum. And a IValueConverter to convert that state into a color. I want to to use the Community toolkit tint behaviour to color a white icon based on the state.
<Image Source="circle_icon.png">
<Image.Behaviors>
<toolkit:IconTintColorBehavior TintColor="{Binding Source={x:Reference ThisComponent},
Path=MyItem.State,
Converter={StaticResource StateToColor}}"/>
</Image.Behaviors>
</Image>
<!-- Label for debugging CORRECT STATE SHOWN-->
<Label Text="{Binding Source={x:Reference Component},
Path=MyItem.State}"/>
State is an enum that can be Green, Blue, Red.
The issue I'm having is that when I change the state, the wrong item in the collection view gets tinted. I have a label next to it to debug, and the correct state is always shown, even after updates. So I know it's not an issue with the property notifications or anything like that, since the label has the correct data at all times.
I can use simple triggers to change the TextColor of the label. That works. But for some reason the tinting doesn't work. I can also use the above converter to colonize a box view, and that works properly. So it's something to do with the community toolkit behaviours and other visual changes that I've seen.
I also noticed a very very similar issue when I try to do an animation on part of the control. The wrong item gets animated.
I suspect (and my conversations with AI reinforce this view) that the issue here has to do with recycling. I suspect that some link between the view displaying the current item has been dissociated with the one that was initialized with it. Or some small time delay has changed the contents just after the visual change is applied. It doesn't seem like Maui has any way to disable recycling, even though Xamarin appears to have that functionality. So I can't be sure that's the issue.
I'm using maui v8.0.100 if that makes any difference.
I'm not sure if this is relevant, but when I adjust the state, I actually save the item to a database, and then I shortly thereafter receive an event from the database that something has changed, and it syncs the ObservableCollection. I have it set up so I don't clear and repopulate the items, but update the existing items with the new data.
I don't think it makes sense to post more code here, because it's a really complicated control with tons of stuff going on.
I'm at my wits end and have tried tons of stuff, and can't seem to solve the issue. Hopefully someone can point me in the right direction for how to approach this problem.
Share Improve this question edited Mar 17 at 13:28 Adam B asked Mar 17 at 4:54 Adam BAdam B 3,8612 gold badges28 silver badges39 bronze badges3 Answers
Reset to default 0Don't use x:Type with x:DataType, i.e.
- Change from:
<DataTemplate x:DataType="{x:Type model:MyItem}">
- to:
<DataTemplate x:DataType="model:MyItem">
Binding Source needs x:DataType here (what type is ThisComponent?):
TintColor="{Binding Source={x:Reference ThisComponent}
Path=MyItem.State,
Converter={StaticResource StateToColor}}"/>
Binding Source needs x:DataType here as well (what type is Component?):
Text="{Binding Source={x:Reference Component},
Path=MyItem.State}"/>
Try setting the BindingContext
of the Behavior
, see note and change.
<Image x:Name="image" >
<Image.Behaviors>
<toolkit:IconTintColorBehavior
BindingContext="{Binding Path=BindingContext, Source={x:Reference image}, x:DataType=Image}"
...
/>
</Image.Behaviors>
</Image>
First, the TintColor="{Binding Source={x:Reference ThisComponent}
and Label Text="{Binding Source={x:Reference Component}
bind to different object. Are they correct?
And then I created a new sample to test your code and every thing worked well. I will show the main code I used.
The customview.xaml:
<ContentView xmlns="http://schemas.microsoft/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft/winfx/2009/xaml"
xmlns:toolkit="http://schemas.microsoft/dotnet/2022/maui/toolkit"
xmlns:local="clr-namespace:TestMaui"
x:Class="TestMaui.MyView"
x:Name="MyComponent">
<ContentView.Resources>
<local:StateToColorConverter x:Key="myconverter"/>
</ContentView.Resources>
<VerticalStackLayout>
<Image
Source="dotnet_bot.png"
HeightRequest="185"
Aspect="AspectFit"
SemanticProperties.Description="dot net bot in a race car number eight" >
<Image.Behaviors>
<toolkit:IconTintColorBehavior TintColor="{Binding Source={x:Reference MyComponent}, Path=MyItem.State, Converter= {x:StaticResource myconverter}}"/>
</Image.Behaviors>
</Image>
<Label Text="{Binding Source={x:Reference MyComponent}, Path=MyItem.State}"/>
</VerticalStackLayout>
</ContentView>
The customview.cs:
public partial class MyView : ContentView
{
public static readonly BindableProperty MyItemProperty =
BindableProperty.Create(
nameof(MyItem),
typeof(MyItem),
typeof(MyView),
default(Nullable));
public MyItem MyItem
{
get => (MyItem)GetValue(MyItemProperty);
set => SetValue(MyItemProperty, value);
}
public MyView()
{
InitializeComponent();
}
}
And the other classes:
public partial class MyItem : ObservableObject
{
[ObservableProperty]
private ItemColor state;
}
public enum ItemColor
{
Green,Blue,Red
}
public class StateToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
if((ItemColor)value == ItemColor.Green)
{
return Colors.Green;
}else if((ItemColor)value==ItemColor.Blue)
{
return Colors.Blue;
}else return Colors.Red;
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Use them in the mainpage.xaml:
<CollectionView x:Name="collec">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="{x:Type local:MyItem}">
<local:MyView MyItem="{Binding .}"/>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
And the mainpage.cs:
public ObservableCollection<MyItem> items;
public MainPage()
{
InitializeComponent();
items = new ObservableCollection<MyItem>();
items.Add(new MyItem() { State = ItemColor.Green });
items.Add(new MyItem() { State= ItemColor.Red });
items.Add(new MyItem() { State= ItemColor.Blue });
collec.ItemsSource = items;
}
private void OnCounterClicked(object sender, EventArgs e)
{
items[0].State = (ItemColor)((int)Math.Abs((int)(items[0].State - 2)));
}
Everything worked well.
本文标签:
版权声明:本文标题:xaml - .Net Maui CollectionView. Changes to one item's view properties affects wrong item. Recycling problem? - Stack Ov 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744578997a2613801.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论