2010-11-10 8 views
1

J'ai une liste qui est remplie avec un contrôle personnalisé. Ça fonctionne bien. Maintenant, je cherche à créer cet effet ...WPF - animation pour différents contrôles via xaml

Lorsque l'utilisateur survole un élément dans la liste, je veux que cet élément augmente son ombre (visible) et tous les autres éléments pour diminuer leur ombre. Cela peut-il être fait? Peut-il être fait en Xaml? J'ai joué avec mais je n'ai pas réussi.

Voici ma configuration actuelle listbox si elle compte ...

<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

Jeff

+0

Atleast, vous devriez considérer le convertisseur. –

+0

Je suis désolé mais je ne comprends pas ce que vous voulez dire – Jeff

Répondre

0

solution Première

Si vos objets remplissent toute votre ItemsPresenter vous pouvez le faire facilement en pur XAML.

Copiez le modèle standard pour la zone de liste et ajouter une bordure autour de la ItemsPresenter, qui calcule la profondeur d'ombre pour tous les articles non plané:

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

Maintenant, ajoutez un élément déclencheur à la frontière de changer quand IsMouseOver = "true":

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

Dans votre ItemTemplate, utilisez FindAncestor pour lier ShadowDepth au ShadowDepth de la frontière:

ShadowDepth="{Binding Path=custom:AppletButton.ShadowDepth, RelativeSource={RelativeSource FindAncestor,Border,1}}" 

Notez que "Path =" est requis lors de l'utilisation des propriétés jointes.

également dans votre ItemTemplate, remplacer le paramètre FindAncestor chaque fois que la souris est sur l'article:

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

Maintenant, chaque fois que la souris est sur le WrapPanel, tous les éléments auront une profondeur d'ombre inférieure, mais si le souris est sur un élément donné, il aura une profondeur d'ombre plus élevée. L'inconvénient de ceci est que si la souris est sur une partie vide du WrapPanel, tous les éléments diminueront leur profondeur d'ombre mais aucun ne sera surligné.

Deuxième solution

Si vous avez besoin des éléments « de-HiLight » dans la zone de liste que lorsque la souris est sur un élément réel (par opposition à sur le panneau), vous devez utiliser du code.

Une manière simple de le faire est de créer une propriété "IsMouseOverAnyItem" et de l'utiliser comme indiqué ci-dessus. Par exemple, vous pouvez sous-classe WrapPanel, et MeasureOverride créer une liste d'objets qui se lient aux propriétés « isMouseOver » de chaque enfant de panneau, quelque chose comme ceci:

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

qui précède suppose que vous avez une classe ValueMonitor qui peut regarder une valeur contraignante et vous informer si cela change.Il pourrait être mis en œuvre quelque chose comme ceci:

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