Enr*_*elo 2 c# data-binding user-controls uwp uwp-xaml
我正在尝试在轮播中绑定一个可重复使用的按钮,我想要实现的是添加 6 个按钮,每个按钮将有一个命令,根据按钮名称将导航到正确的页面。
\n\n我可以通过这样做来做到这一点:
\n\n<toolkitcontrols:Carousel x:Name="NavigationMenuCarouselPanel"\n HorizontalAlignment="Center"\n VerticalAlignment="Center"\n Orientation="Horizontal"\n ItemsSource="{x:Bind ViewModel.MenuList, Mode=OneWay}"\n ItemMargin="25"\n ItemDepth="160"\n ItemRotationX="180"\n ItemRotationY="25"\n ItemRotationZ="0"\n SelectedIndex="2"\n Grid.Row="1">\n <toolkitcontrols:Carousel.EasingFunction>\n <CubicEase EasingMode="EaseOut"/>\n </toolkitcontrols:Carousel.EasingFunction>\n <Button Command="{x:Bind ViewModel.NavigateToPage1, Mode=OneWay}"\n Content="{x:Bind ViewModel.Name, Mode=OneWay}"/>\n </toolkitcontrols:Carousel>\nRun Code Online (Sandbox Code Playgroud)\n\n如果我这样做,我将添加 5 个以上的按钮,并且我必须为每个按钮编写属性。
\n\n因此,我想使用 UserControl 并编写如下内容:
\n\n<toolkitcontrols:Carousel x:Name="NavigationMenuCarouselPanel"\n HorizontalAlignment="Center"\n VerticalAlignment="Center"\n Orientation="Horizontal"\n ItemsSource="{x:Bind ViewModel.MenuList, Mode=OneWay}"\n ItemMargin="25"\n ItemDepth="160"\n ItemRotationX="180"\n ItemRotationY="25"\n ItemRotationZ="0"\n SelectedIndex="2"\n Grid.Row="1">\n <toolkitcontrols:Carousel.EasingFunction>\n <CubicEase EasingMode="EaseOut"/>\n </toolkitcontrols:Carousel.EasingFunction>\n <toolkitcontrols:Carousel.ItemTemplate>\n <DataTemplate x:DataType="data:ButtonInfo">\n <usercontrolvm:NavigationMenuButtonTemplate NavigateToPageCommand="{Binding NavigateToPageCommand}"/>\n </DataTemplate>\n </toolkitcontrols:Carousel.ItemTemplate>\n </toolkitcontrols:Carousel>\nRun Code Online (Sandbox Code Playgroud)\n\n但我没能做到这一点,我找到了一些教程,但据我所知,所有这些都会让我写出这样的代码:
\n\n<usercontrolvm:NavigationMenuButtonTemplate NavigateToPageCommand="{Binding NavigateToPageCommand}"/>\nRun Code Online (Sandbox Code Playgroud)\n\n大约 6 次,我不知道如何将 DataTemplate 的 x:DataType 作为我的属性列表。
\n\n这是我的 UserControl.xaml.cs
\n\npublic sealed partial class NavigationMenuButtonTemplate : UserControl\n{\n public ButtonInfo ButtonInfo => (DataContext as ButtonInfo);\n\n public NavigationMenuButtonTemplate()\n {\n this.InitializeComponent();\n Loaded += NavigationMenuButtonTemplate_Loaded;\n }\n\n private void NavigationMenuButtonTemplate_Loaded(object sender, RoutedEventArgs e)\n {\n Bindings.Update();\n }\n\n public DelegateCommand NavigateToPageCommand\n {\n get { return (DelegateCommand)GetValue(NavigateToPageCommandProperty); }\n set { SetValue(NavigateToPageCommandProperty, value); }\n }\n\n // Using a DependencyProperty as the backing store for NavigateToPageCommand. This enables animation, styling, binding, etc...\n public static readonly DependencyProperty NavigateToPageCommandProperty =\n DependencyProperty.Register("NavigateToPageCommand", \n typeof(DelegateCommand), \n typeof(NavigationMenuButtonTemplate), \n new PropertyMetadata(0));\n}\nRun Code Online (Sandbox Code Playgroud)\n\n这是我的 ButtonInfo.cs
\n\npublic class ButtonInfo\n{\n public string Symbol { get; set; }\n public string FontFamily { get; set; }\n public string MenuName { get; set; }\n public string BenefitKind { get; set; }\n public string Status { get; set; } \n}\nRun Code Online (Sandbox Code Playgroud)\n\n这是我的 UserControl.xaml
\n\n<Button x:Name="NavigationMenuTemplate"\n Width="300"\n Height="300"\n Command="{Binding NavigateToPageCommand, ElementName=root, Mode=OneWay}">\n <Grid x:Name="ButtonLayout">\n <Grid.RowDefinitions>\n <RowDefinition Height="*"/>\n <RowDefinition Height="Auto"/>\n <RowDefinition Height="Auto"/>\n </Grid.RowDefinitions>\n <Grid.ColumnDefinitions>\n <ColumnDefinition Width="*"/>\n <ColumnDefinition Width="*"/>\n </Grid.ColumnDefinitions>\n <TextBlock x:Name="NavigationMenuIconTextBlock"\n Grid.Row="0"\n Grid.Column="0"\n Grid.ColumnSpan="2"\n FontFamily="{x:Bind ButtonInfo.FontFamily, Mode=OneWay, FallbackValue=\'Webdings\'}"\n Text="{x:Bind ButtonInfo.Symbol, Mode=OneWay, FallbackValue=\'‘\'}"\n FontSize="150"\n Foreground="Black"\n VerticalAlignment="Center"\n HorizontalAlignment="Center"/>\n <TextBlock x:Name="NavigationMenuButtonNameTextBlock"\n Grid.Row="1"\n Grid.Column="0"\n Grid.ColumnSpan="2"\n Text="{x:Bind ButtonInfo.MenuName, Mode=OneWay, FallbackValue=\'CALCULADORA JORNADAS EXTRAORDINARIAS\'}"\n FontSize="12"\n Foreground="Black"\n HorizontalAlignment="Center"/>\n <TextBlock x:Name="NavigationMenuButtonBenefitKindTextBlock"\n Grid.Row="2"\n Grid.Column="0"\n Text="{x:Bind ButtonInfo.BenefitKind, Mode=OneWay, FallbackValue=\'Subscripci\xc3\xb3n\'}"\n FontSize="10"\n Foreground="Black"\n HorizontalAlignment="Left"/>\n <TextBlock x:Name="NavigationMenuButtonStatusTextBlock"\n Grid.Row="2"\n Grid.Column="1"\n Text="{x:Bind ButtonInfo.Status, Mode=OneWay, FallbackValue=\'Vigente\'}"\n FontSize="10"\n Foreground="Black"\n HorizontalAlignment="Right"/>\n </Grid> \n </Button>\nRun Code Online (Sandbox Code Playgroud)\n\n有人可以帮助我并指出正确的方向吗?\n我错过了什么?
\n你的问题中的方法ItemTemplate实际上是在正确的轨道上。
最后,您的 XAML 将类似于以下内容(仅包含一些属性,但您明白了) -
<toolkitcontrols:Carousel ItemsSource="{x:Bind ButtonInfoCollection}">
<toolkitcontrols:Carousel.ItemTemplate>
<DataTemplate x:DataType="local:ButtonInfo">
<local:NavigationMenuButton NavigateToPageCommand="{Binding DataContext.NavigateToPageCommand, ElementName=MyPageName}"
NavigateToPageCommandParameter="{x:Bind PageType}"
MenuName="{x:Bind MenuName}"
SymbolPath="{x:Bind Symbol}" />
</DataTemplate>
</toolkitcontrols:Carousel.ItemTemplate>
</toolkitcontrols:Carousel>
Run Code Online (Sandbox Code Playgroud)
考虑到上面的结构,您只需将这些属性公开为用户控件中的依赖属性NavigationMenuButton。请参阅下面的一个简单示例 -
导航菜单按钮 XAML
<UserControl x:Class="DesignTest.NavigationMenuButton">
<!--If any of the properties can be updated, change the binding Mode to OneWay-->
<Button Command="{x:Bind NavigateToPageCommand, Mode=OneWay}" CommandParameter="{x:Bind NavigateToPageCommandParameter}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image x:Name="SymbolImage" Stretch="UniformToFill" />
<TextBlock Text="{x:Bind MenuName, FallbackValue='JORNADAS EXTRAORDINARIAS', TargetNullValue='JORNADAS EXTRAORDINARIAS'}" Grid.Column="1" />
</Grid>
</Button>
</UserControl>
Run Code Online (Sandbox Code Playgroud)
NavigationMenuButton 代码隐藏
public sealed partial class NavigationMenuButton : UserControl
{
public NavigationMenuButton()
{
InitializeComponent();
}
public ICommand NavigateToPageCommand
{
get => (ICommand)GetValue(NavigateToPageCommandProperty);
set => SetValue(NavigateToPageCommandProperty, value);
}
public static readonly DependencyProperty NavigateToPageCommandProperty = DependencyProperty.Register(
"NavigateToPageCommand", typeof(ICommand), typeof(NavigationMenuButton), new PropertyMetadata(null));
public object NavigateToPageCommandParameter
{
get => GetValue(NavigateToPageCommandParameterProperty);
set => SetValue(NavigateToPageCommandParameterProperty, value);
}
public static readonly DependencyProperty NavigateToPageCommandParameterProperty = DependencyProperty.Register(
"NavigateToPageCommandParameter", typeof(object), typeof(NavigationMenuButton), new PropertyMetadata(null));
public string MenuName
{
get => (string)GetValue(MenuNameProperty);
set => SetValue(MenuNameProperty, value);
}
public static readonly DependencyProperty MenuNameProperty = DependencyProperty.Register(
"MenuName", typeof(string), typeof(NavigationMenuButton), new PropertyMetadata(null));
public string SymbolPath
{
get => (string)GetValue(SymbolPathProperty);
set => SetValue(SymbolPathProperty, value);
}
public static readonly DependencyProperty SymbolPathProperty = DependencyProperty.Register(
"SymbolPath", typeof(string), typeof(NavigationMenuButton), new PropertyMetadata(null, (s, e) =>
{
// We don't do the x:Bind for this property in XAML because the Image control's Source property
// doesn't accept a string but a BitmapImage, so one workaround is to do the conversion here.
var self = (NavigationMenuButton)s;
var image = self.SymbolImage;
var symbolPath = (string)e.NewValue;
image.Source = new BitmapImage(new Uri(self.BaseUri, symbolPath ?? "/Assets/default_path"));
}));
}
Run Code Online (Sandbox Code Playgroud)
请注意,您需要在类PageType中包含一个属性ButtonInfo以用于导航目的。
public Type PageType { get; set; }
Run Code Online (Sandbox Code Playgroud)
我个人不喜欢在项目级别(即在类中ButtonInfo)定义导航命令,相反,我使用ElementName的数据模板中的绑定Carousel来搜索级别并绑定到NavigateToPageCommand页面的 中定义的DataContext,即该页面的ViewModel.
这意味着这ViewModel将同时具有ButtonInfoCollection和NavigateToPageCommand定义,如下所示 -
public ObservableCollection<ButtonInfo> ButtonInfoCollection { get; } = new ObservableCollection<ButtonInfo>
{
new ButtonInfo { MenuName = "New Menu", PageType = typeof(BlankPage1), Symbol = "/Assets/StoreLogo.png" }
};
public DelegateCommand<Type> NavigateToPageCommand { get; } = new DelegateCommand<Type>(type =>
App.Frame.Navigate(type));
Run Code Online (Sandbox Code Playgroud)
我希望这一切都有道理。祝你好运!