2015-07-29 8 views
5

Also, ich weiß sehr wenig über Dekorateure/Adorner, aber bekam eine gute Antwort here, die sie verwendet.Warum funktioniert meine benutzerdefinierte Decorator/Adorner Funktion nicht, wenn Bool zu True wechselt?

Ich habe versucht, sie zu implementieren, aber sie scheinen nicht zu arbeiten, wie sie für die Person, die die Antwort gab. Ich habe versucht, alles so identisch wie möglich zu halten.

Hier meine XAML ist:

<models:TipFocusDecorator x:Name="LoginDecorator" 
     TipText="Enter your username and password and click 'Login'" 
     IsOpen="{Binding ShowLoginTip}" 
     Grid.Column="1" Grid.Row="1"> 
    <Image Grid.Column="1" Grid.Row="1" Source="{Binding EnemyImagePath, FallbackValue={StaticResource DefaultImage}}" MaxWidth="500" MaxHeight="500"> 
     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="MouseUp"> 
       <i:InvokeCommandAction Command="{Binding EnemyAttack}" /> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 
    </Image> 
</models:TipFocusDecorator> 

public class TipFocusDecorator : Decorator 
{ 

    public bool IsOpen 
    { 
     get { return (bool)GetValue(IsOpenProperty); } 
     set { SetValue(IsOpenProperty, value); } 
    } 
    // Using a DependencyProperty as the backing store for Open. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty IsOpenProperty = 
     DependencyProperty.Register("IsOpen", typeof(bool), typeof(TipFocusDecorator), 
     new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, IsOpenPropertyChanged)); 


    public string TipText 
    { 
     get { return (string)GetValue(TipTextProperty); } 
     set { SetValue(TipTextProperty, value); } 
    } 
    // Using a DependencyProperty as the backing store for TipText. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty TipTextProperty = 
     DependencyProperty.Register("TipText", typeof(string), typeof(TipFocusDecorator), new UIPropertyMetadata(string.Empty)); 


    public bool HasBeenShown 
    { 
     get { return (bool)GetValue(HasBeenShownProperty); } 
     set { SetValue(HasBeenShownProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for HasBeenShown. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty HasBeenShownProperty = 
     DependencyProperty.Register("HasBeenShown", typeof(bool), typeof(TipFocusDecorator), new UIPropertyMetadata(false)); 

    private static void IsOpenPropertyChanged(object sender, DependencyPropertyChangedEventArgs e) 
    { 
     var decorator = sender as TipFocusDecorator; 

     if ((bool)e.NewValue) 
     { 
      if (!decorator.HasBeenShown) 
       decorator.HasBeenShown = true; 

      decorator.Open(); 
     } 

     if (!(bool)e.NewValue) 
     { 
      decorator.Close(); 
     } 
    } 

    TipFocusAdorner adorner; 

    protected void Open() 
    { 
     adorner = new TipFocusAdorner(this.Child); 
     var adornerLayer = AdornerLayer.GetAdornerLayer(this.Child); 
     adornerLayer.Add(adorner); 

     MessageBox.Show(TipText); // Change for your custom tip Window 
     IsOpen = false; 
    } 

    protected void Close() 
    { 
     var adornerLayer = AdornerLayer.GetAdornerLayer(this.Child); 
     adornerLayer.Remove(adorner); 
     adorner = null; 
    } 

} 

Hier ist die Adorner Klasse:

public class TipFocusAdorner : Adorner 
{ 
    public TipFocusAdorner(UIElement adornedElement) 
     : base(adornedElement) 
    { 
    } 

    protected override void OnRender(System.Windows.Media.DrawingContext drawingContext) 
    { 
     base.OnRender(drawingContext); 

     var root = Window.GetWindow(this); 
     var adornerLayer = AdornerLayer.GetAdornerLayer(AdornedElement); 
     var presentationSource = PresentationSource.FromVisual(adornerLayer); 
     Matrix transformToDevice = presentationSource.CompositionTarget.TransformToDevice; 

     var sizeInPixels = transformToDevice.Transform((Vector)adornerLayer.RenderSize); 
     RenderTargetBitmap rtb = new RenderTargetBitmap((int)(sizeInPixels.X), (int)(sizeInPixels.Y), 96, 96, PixelFormats.Default); 

     var oldEffect = root.Effect; 
     root.Effect = new BlurEffect(); 
     rtb.Render(root); 
     root.Effect = oldEffect; 

     drawingContext.DrawImage(rtb, adornerLayer.TransformToVisual(AdornedElement).TransformBounds(new Rect(adornerLayer.RenderSize))); 
     drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(22, 0, 0, 0)), null, adornerLayer.TransformToVisual(AdornedElement).TransformBounds(new Rect(adornerLayer.RenderSize))); 
     drawingContext.DrawRectangle(new VisualBrush(AdornedElement) { AlignmentX = AlignmentX.Left, TileMode = TileMode.None, Stretch = Stretch.None }, 
      null, 
      AdornedElement.RenderTransform.TransformBounds(new Rect(AdornedElement.DesiredSize))); 
    } 
} 

Und schließlich, hier ist meine Viewmodel:

private ICommand testDebug; 
public ICommand TestDebug 
{ 
    get 
    { 
     if (testDebug == null) 
     { 
      testDebug = new RelayCommand(param => this.TestDebugEx(), null); 
     } 
     return testDebug; 
    } 
} 
private void TestDebugEx() 
{ 
    ShowLoginTip = true; 
    OnPropertyChanged("ShowLoginTip"); 
} 

public bool ShowLoginTip = true; 

Wenn ich drücken Sie die Taste, die ruft den Befehl auf, der Befehl wird ausgeführt und der Wert von ShowLoginTip ändert sich in "true". Es wird jedoch nichts im Decorator usw. ausgeführt.

Antwort

1

Damit die Bindung in WPF funktioniert, sollte ShowLoginToolTip eine Eigenschaft sein.

ändern es auf diese

private bool _showLoginToolTip; 

public bool ShowLoginToolTip 
{ 
    get 
     { 
     return _showLoginToolTip; 
     } 
    set 
     { 
     _showLoginToolTip = value; 
     OnPropertyChanged("ShowLoginTip"); 
     } 
} 

private void TestDebugEx() 
{ 
    ShowLoginTip = true; 
}