On Uno Platform project, using several data templates for TabViewItem
, TreeViewItem
and ListViewItem
, trying to fire commands via various events, like ItemInvoked
(TreeView), DoubleTapped
(ListView), CloseRequested
(TabView).
Strangely enough it works for few invocations, then it stops. Note that (also the same) commands bound to Buttons via their Command
binding continue working.
Example of TabView close attempt. Typically works for first 3 to 5 tabs:
<DataTemplate x:Key="HtmlFileTemplate" x:DataType="local:FileContentViewModel">
<TabViewItem Header="{x:Bind Info.Name}">
<StackPanel Orientation="Vertical">
<TextBlock Text="{x:Bind Content}" />
<!--
This just works:
-->
<Button Command="{x:Bind CloseCommand}">Invoke FileContentViewModel.CloseCommand</Button>
</StackPanel>
<!--
This stops working after few invocations
(typically together with all other Interaction.Behaviors bindings):
-->
<i:Interaction.Behaviors>
<ic:EventTriggerBehavior EventName="CloseRequested">
<ic:InvokeCommandAction Command="{x:Bind CloseCommand}" />
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
</TabViewItem>
</DataTemplate>
<local:TabsTemplateSelector x:Key="TabsTemplateSelector" HtmlFileTemplate="{StaticResource HtmlFileTemplate}" ... />
...
<TabView TabItemsSource="{x:Bind ViewModel.Tabs}" TabItemTemplateSelector="{StaticResource TabsTemplateSelector}">
</TabView>
I hope, there is some flagrant issue in my usage I can't simply see. Any Help appreciated. Using latest uno stuff (WinUI, dotnet6), debugging on Windows head:
dotnet new unoapp -o UnoWinUI3AppName
<PackageReference Include="CommunityToolkit.Mvvm" Version="7.1.2" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.1.3" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.1" />
<PackageReference Include="Uno.Microsoft.Xaml.Behaviors.Interactivity.WinUI" Version="2.3.0" />
<PackageReference Include="Uno.Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.3.0" />
Still trying to find minimal sample exhibiting the mentioned issues.
Also tried to check the XAML generated code, but it is too much... well... generated :-(
EDIT:
"Simplified" the use case to following:
- Have
TabView
on a page. - First tab contains
ListView
with items. - Other tabs contain "opened" items (dummy record).
- Item opens on double-click (
DoubleTapped
) inListView
on first page. - Item closes on
X
click on a tab (inTabView
). - Both
TabView
andListView
useDataTemplate
s. - Separate UI from code as much as possible (binding, commands, VMs, etc.).
- Based on default WinUI "Hello World" app template.
- Project files
EDIT 2: For anyone interested, based on Andrew KeepCoding's hints and linked issue answers, I mixed code behind with custom attaching of the behaviors to the templated items via new attached property:
public static class InteractionEx
{
public static readonly DependencyProperty AttachBehaviorsProperty = DependencyProperty.RegisterAttached
(
"AttachBehaviors",
typeof(object),
typeof(FrameworkElement),
new PropertyMetadata(false, AttachBehaviorsChanged)
);
public static object GetAttachBehaviors(DependencyObject o) => o.GetValue(AttachBehaviorsProperty);
public static void SetAttachBehaviors(DependencyObject o, object value) => o.SetValue(AttachBehaviorsProperty, value);
private static void AttachBehaviorsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var behaviors = e.NewValue switch
{
Behavior single => new BehaviorCollection { single },
BehaviorCollection multiple => multiple,
_ => null,
};
Interaction.SetBehaviors(d, behaviors);
}
}
In XAML the behaviors then can be attached to a control like:
<ListView ItemsSource="{x:Bind Items}" ItemTemplateSelector="{StaticResource ListItemTemplateSelector}" SelectedItem="{x:Bind SelectedItem, Mode=TwoWay}">
<local:InteractionEx.AttachBehaviors>
<interactivity:BehaviorCollection>
<core:EventTriggerBehavior EventName="DoubleTapped">
<core:InvokeCommandAction Command="{x:Bind OpenCommand}" />
<core:CallMethodAction MethodName="Open" TargetObject="{x:Bind}" />
</core:EventTriggerBehavior>
</interactivity:BehaviorCollection>
</local:InteractionEx.AttachBehaviors>
</ListView>
1条答案
按热度按时间ryevplcw1#
我想您会发现这些answers很有帮助。
但是让我建议另一个选择。我花了一些时间在你的repro项目上,在我看来,我认为如果你放弃Interaction.Behaviors.代码隐藏如果它是UI相关的,没有业务逻辑,它会更干净和可读。