如何在Silverlight中使用MVVM时使(矢量)路径可选
本文关键字:矢量 路径 时使 MVVM Silverlight | 更新日期: 2023-09-27 18:23:58
我正在用C#和MVVM在Silverlight中设计一个应用程序。在其中一页上,我有一个由几个Path
组成的图像(如在视觉中,而不是类型Image
)。在这种情况下,它们形成了一张脸,我希望用户能够选择几个部分(眼睛、鼻子、耳朵…)。每个部分都是一个单独的Path
。
这个想法是用户可以选择其中一个矢量并使用它。我希望选择的矢量能改变颜色。
我可以把bool
转换成选定的颜色,这不是问题。问题在于添加选择逻辑。
我的想法是将其封装在ListBox
中,编辑ItemTemplate
以包含Path
,但这个位置错误地指定了路径。即使在应用了边距之类的东西之后,我也无法正确地获得它。
有人对此有任何经验或指导吗?
提前感谢!
答案:
1)将ItemsPanel模板更改为您的容器:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Width="208"
Height="391" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
2)设置项目来源:
这里的技巧是,定位/附加的属性只适用于ListBox的直接子级。在这种情况下,我使用Canvas.Top和Canvas.Left。解决方案是将每个项包装在一个额外的ListBoxItem中,并将这些属性应用于ListBoxItem。(如果您不这样做,默认情况下会发生这种情况)。
<ListBox>
<ListBoxItem Canvas.Left="10" Canvas.Top="5">
<Path Data="..." Height="200" Width="200" Fill="Black" />
</ListBoxItem>
</ListBox>
尝试在绑定到ViewModel上的命令的Path
上设置MouseLeftButtonDown
事件处理程序。应该能够使用处理程序中的sender
参数来确定要修改哪个Path
。
对于ListBox
方法,您是否尝试修改ItemsPanel
并使用Canvas
?
如果我理解正确,您可以使用VisualStateManager为FocusStates添加VisualStateGroup,就像您在标准按钮上看到的那样,将不同的填充或边框应用于所选路径。从本质上讲,你会让每条路径表现得像一个按钮控件,根据其焦点显示不同的视觉状态。
(将此示例更改为默认复选框模板作为示例)如果您需要,我可以制作一个示例。
<Style TargetType="CheckBox" x:Key="DefaultCheckBoxStyle">
<Setter Property="FontFamily" Value="{StaticResource ContentFontFamily}"/>
<Setter Property="FontSize" Value="{StaticResource ContentFontSize}"/>
<Setter Property="Background" Value="{StaticResource NormalBrush}"/>
<Setter Property="Foreground" Value="{StaticResource TextContentBrush}"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="Padding" Value="4,1,0,0"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Value="{StaticResource NormalBorderBrush}" Property="BorderBrush"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<Grid x:Name="grid" RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Grid.RenderTransform>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition From="Normal" GeneratedDuration="0:0:0.01" To="MouseOver">
<VisualTransition.GeneratedEasingFunction>
<ExponentialEase EasingMode="EaseIn" Exponent="7"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
<VisualTransition From="MouseOver" GeneratedDuration="0:0:0.1" To="Normal">
<VisualTransition.GeneratedEasingFunction>
<CircleEase EasingMode="EaseIn"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="MouseOverRectangleFill" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="1.0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PressedBorder" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="1.0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="1.05"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="1.05"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0.3"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="DisabledVisualElement" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="1.0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="CheckIcon">
<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="CheckedRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0.6"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked"/>
<VisualState x:Name="Indeterminate">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="IndeterminateIcon">
<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="IndeterminateRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0.6"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentFocusVisualElement">
<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
<VisualStateGroup x:Name="ValidationStates">
<VisualState x:Name="Valid"/>
<VisualState x:Name="InvalidUnfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="InvalidFocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" Storyboard.TargetName="validationTooltip">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>True</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="21"/>
</Grid.ColumnDefinitions>
<Grid HorizontalAlignment="Right" VerticalAlignment="Top" Grid.Column="1" Margin="5,0,0,0">
<Grid Width="16" Height="16">
<Rectangle x:Name="Background" Fill="{StaticResource BlankBackgroundBrush}" StrokeThickness="{TemplateBinding BorderThickness}" Stroke="{StaticResource BaseBrush7}" />
<Rectangle x:Name="BackgroundInner" Fill="{TemplateBinding Background}" Margin="1" StrokeThickness="{TemplateBinding BorderThickness}" Stroke="{TemplateBinding BorderBrush}"/>
<Rectangle x:Name="MouseOverRectangleFill" Fill="{StaticResource MouseOverBrush}" StrokeThickness="2" Opacity="0" Margin="3"/>
<Rectangle x:Name="MouseOverRectangle" StrokeThickness="2" Stroke="{StaticResource MouseOverBrush}" Opacity="0"/>
<Border x:Name="PressedBorder" BorderThickness="1" BorderBrush="{StaticResource MouseOverBrush}" Opacity="0" />
<Rectangle x:Name="ContentFocusVisualElement" StrokeThickness="1" IsHitTestVisible="false" Opacity="0" Stroke="{StaticResource FocusedBrush}" />
<Rectangle x:Name="DisabledVisualElement" Fill="{StaticResource DisabledBackgroundBrush}" Stroke="{StaticResource DisabledBackgroundBrush}" Opacity="0" RadiusY="1" RadiusX="1" />
<Rectangle x:Name="CheckedRectangle" StrokeThickness="0.5" Stroke="{StaticResource BaseBrush4}" Opacity="0" RadiusX="0.5" RadiusY="0.5"/>
<Path x:Name="CheckIcon" Data="M335.69366,107.11728 L339,111.375 347.09859,99.975309" HorizontalAlignment="Center" Stretch="Fill" Stroke="{StaticResource BaseBrush4}" UseLayoutRounding="False" VerticalAlignment="Center" StrokeThickness="2" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Margin="3.5" Opacity="0"/>
<Rectangle x:Name="IndeterminateRectangle" StrokeThickness="2" Stroke="{StaticResource BaseBrush4}" Opacity="0"/>
<Rectangle x:Name="IndeterminateIcon" Fill="{StaticResource BaseBrush3}" Height="2" Opacity="0" Width="6"/>
<Border x:Name="ValidationErrorElement" BorderBrush="{StaticResource ControlsValidationBrush}" BorderThickness="1" CornerRadius="1" Margin="1" ToolTipService.PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Visibility="Collapsed">
<ToolTipService.ToolTip>
<ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}">
<ToolTip.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="validationTooltip">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>true</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToolTip.Triggers>
</ToolTip>
</ToolTipService.ToolTip>
<Grid Background="Transparent" HorizontalAlignment="Right" Height="10" Margin="0,-4,-4,0" VerticalAlignment="Top" Width="10">
<Path Data="M 1,0 L5,0 A 2,2 90 0 1 7,2 L7,6 z" Fill="{StaticResource ValidationBrush5}" Margin="0,3,0,0"/>
<Path Data="M 0,0 L2,0 L 7,5 L7,7" Fill="{StaticResource BlankBackgroundBrush}" Margin="0,3,0,0"/>
</Grid>
</Border>
</Grid>
</Grid>
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
用解决方案更新了我的问题,再次发布,以便我可以将其标记为已回答:
答案:
1)将ItemsPanel模板更改为您的容器:
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Width="208"
Height="391" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
2)设置项目来源:
这里的技巧是,定位/附加的属性只适用于ListBox的直接子级。在这种情况下,我使用Canvas.Top和Canvas.Left。解决方案是将每个项包装在一个额外的ListBoxItem中,并将这些属性应用于ListBoxItem。(如果您不这样做,默认情况下会发生这种情况)。
<ListBox>
<ListBoxItem Canvas.Left="10" Canvas.Top="5">
<Path Data="..." Height="200" Width="200" Fill="Black" />
</ListBoxItem>
</ListBox>