Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why wont my custom decorator / adorner function when bool changes to true?

So, I know very little about decorators / adorners, but was given a great answer here which uses them.

I have tried to implement them, but they ust dont seem to work as they do for the person who gave the answer. I have tried to keep everything as identical as I can.

Here is my XAML:

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

}

Here is the Adorner class:

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

And finally, here is my 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;

When I press the button which calls the command, the command runs fine, and the value of ShowLoginTip changes to true. However, it doesn't run anything in the decorator etc.

like image 608
pingu2k4 Avatar asked Nov 09 '22 08:11

pingu2k4


1 Answers

For the Binding to work in WPF, ShowLoginToolTip should be a property.

Change it to this

private bool _showLoginToolTip;

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

private void TestDebugEx()
{
    ShowLoginTip = true;
}
like image 159
Carbine Avatar answered Nov 14 '22 23:11

Carbine