2010-11-10 61 views
1

我有一個用自定義控件填充的列表框。它工作正常。現在我正在創建這種效果...WPF - 通過xaml爲不同的控件提供動畫

當用戶將鼠標懸停在列表框中的某個項目上時,我希望該項目增加它的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

至少,你應該考慮轉換器。 – 2010-11-10 18:08:22

+0

我很抱歉,但我不明白你的意思 – Jeff 2010-11-10 18:10:28

回答

0

首先解決

如果您的項目填滿整個ItemsPresenter你可以很容易在純XAML中完成。

複製的標準模板列表框和周圍添加ItemsPresenter,這將計算陰影深度爲所有非徘徊項的邊框:

<Border custom:AppletButton.ShadowDepth="15"> 
    <ItemsPresenter /> 
</Border> 

現在添加一個觸發器到邊境時更改此IsMouseOver = 「真」:

<Border.Triggers> 
    <Trigger Property="IsMouseOver" Value="True"> 
    <Setter Property="custom:AppletButton.ShadowDepth" Value="10" /> 
    </Trigger> 
</Border.Triggers> 

在你的ItemTemplate,使用FindAncestor來ShadowDepth綁定到邊框的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」性能對象列表,像這樣:

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); 
    } 
} 

上述假設你有一個ValueMonitor類,可以觀察一個綁定值並在其更改時通知您。它可能是這樣實現的:

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); 
    } 
}