我有一个填充了自定义控件的列表框。它工作正常。现在我想创造这种效果......
当用户将鼠标悬停在列表框中的某个项目上时,我希望该项目增加其shadowdepth(已显示)和所有其他项目以减少其shadowdepth。可以这样做吗?可以在Xaml中完成吗?
我玩过它但是没有成功。
如果重要的话,这是我当前的列表框设置......
<ListBox ItemsSource="{Binding Path=Applets}" Margin="10,92,10,10" ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<custom:AppletButton
Margin="{Binding Path=DesiredMargin}"
Width="{Binding Path=DesiredWidth}"
Height="{Binding Path=DesiredHeight}"
CornerRadius="{Binding Path=CornerRoundness}"
BackgroundImage="{Binding Path=BackImage}"
BorderThickness="{Binding Path=BorderWidth}"
Text ="{Binding Path=Title}"
TextColor ="{Binding Path=TitleColor}"
AlternateText ="{Binding Path=Description}"
AlternateTextColor ="{Binding Path=DescriptionColor}"
AlternateTextShadowColor="White"
AlternateTextSize="56"
TextShadowColor="Gray"
CaptionTextSize="72"
ToolTip="{Binding Path=ToolTip}"
ShadowDepth="15"
SaturationLevel="{Binding Path=Saturation}"
Tag="{Binding Path=Tag}">
<custom:AppletButton.BorderBrush>
<ImageBrush ImageSource="{Binding BorderBrushImage}" />
</custom:AppletButton.BorderBrush>
<custom:AppletButton.BitmapEffect>
<DropShadowBitmapEffect x:Name="AppletShadow" ShadowDepth="5" Opacity="0.5" Softness="0.5" />
</custom:AppletButton.BitmapEffect>
</custom:AppletButton>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
TIA
杰夫
答案 0 :(得分:0)
第一个解决方案
如果您的商品填满整个ItemsPresenter,您可以在纯XAML中轻松完成。
复制ListBox的标准模板,并在ItemsPresenter周围添加一个Border,它将计算所有非悬停项目的阴影深度:
<Border custom:AppletButton.ShadowDepth="15">
<ItemsPresenter />
</Border>
现在向边框添加一个触发器,以便在IsMouseOver =“true”时更改此值:
<Border.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="custom:AppletButton.ShadowDepth" Value="10" />
</Trigger>
</Border.Triggers>
在你的ItemTemplate中,使用FindAncestor将ShadowDepth绑定到Border的ShadowDepth:
ShadowDepth="{Binding Path=custom:AppletButton.ShadowDepth, RelativeSource={RelativeSource FindAncestor,Border,1}}"
请注意,使用附加属性时需要“Path =”。
同样在你的ItemTemplate中,只要鼠标悬停在项目上,就覆盖FindAncestor设置:
<custom:AppletButton.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ShadowDepth" Value="40" />
</Trigger>
</custom:AppletButton.Triggers>
现在,只要鼠标在WrapPanel上方,所有项目的阴影深度都会降低,但如果鼠标位于给定项目上方,则阴影深度会更高。
这方面的缺点是,如果鼠标位于WrapPanel的空白部分上,则所有项目都会降低其阴影深度,但不会有任何高度。
第二个解决方案
如果当鼠标悬停在实际项目上(而非在面板上方)时,如果您需要在列表框中 执行此操作的一种简单方法是创建“IsMouseOverAnyItem”属性并使用它,如上所示。例如,您可以继承WrapPanel,并在MeasureOverride中创建一个绑定到每个面板子项的“IsMouseOver”属性的对象列表,如下所示: 以上假设您有一个可以监视绑定值的ValueMonitor类,并在它发生更改时通知您。它可能实现如下:public class MyWrapPanel : WrapPanel
{
List<ValueMonitor> _monitors;
public bool IsMouseOverAnyItem { get { return (bool)GetValue(IsMouseOverAnyItemProperty); } set { SetValue(IsMouseOverAnyItemProperty, value); } }
public static readonly DependencyProperty IsMouseOverAnyItemProperty = DependencyProperty.Register("IsMouseOverAnyItem", typeof(bool), typeof(MyWrapPanel));
protected override Size MeasureOverride(Size constraint)
{
if(_monitors!=null) _monitors.ForEach(monitor => monitor.Disable());
_monitors = (
from child in Children.OfType<object>()
select new ValueMonitor(new Binding("IsMouseOver") { Source=child },
() => Update()) // ValueChangedAction
).ToList();
Update();
return base.MeasureOverride(constraint);
}
public void Update()
{
IsMouseOverAnyItem = _monitors.All(monitor => (bool)monitor.Value);
}
}
public class ValueMonitor : DependencyObject
{
Action _valueChangedAction;
public object Value { get { return (object)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } }
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(ValueMonitor), new PropertyMetadata
{
PropertyChangedCallback = (obj, e) => ((ValueMonitor)obj)._valueChangedAction()
});
public ValueMonitor(BindingBase binding, Action valueChangedAction)
{
_valueChangedAction = valueChangedAction;
BindingOperations.SetBinding(this, ValueProperty, binding);
}
public void Disable()
{
ClearValue(ValueProperty);
}
}