0

I'm in need to inform a client-component on position changes of Controls in a Grid.

Is there a possibilty to get informed if someone calls Grid.SetLeft(control, x)?

Of course I can implement my own Left-Properties which calls Grid.SetLeft first and then the callback, but if someone else moves the Control the other way, I get not informed.

Thanks for help.

GreenEyedAndy
  • 1,485
  • 1
  • 14
  • 31
  • possible duplicate of [How can I add logic to an existing dependency-property callback?](http://stackoverflow.com/questions/1310090/how-can-i-add-logic-to-an-existing-dependency-property-callback) – AkselK Feb 06 '14 at 11:40
  • I you read the link, you find out it's not working with SetLeft. – GreenEyedAndy Feb 06 '14 at 12:34
  • Well, first of all: there is no such thing as Grid.SetLeft. Are you sure you are not talking about Canvas.SetLeft? In which case I have implemented the code in the answer, and it does indeed work. Meh, I'll just post an answer. Hang on. – AkselK Feb 06 '14 at 12:43

1 Answers1

3

As mentioned in the linked answer, you can simply use OverrideMetadata to register your own callback.

I'm assuming you are using Canvas, and not Grid, since Canvas is the component with SetLeft.

In the following example I add two components, a Button and a TextBlock, to a Canvas, and changes their position when they are clicked.
I then register three overrides, one which uses button as the type, one with textblock, and one with UIElement. Try to run the application as it is, and notice how the UIElement does not trigger. Remove the two first lines, the callbacks for the Button and TextBlock, and see how it now uses the UIElement callback.
You can use this to filter out which types you need to listen to.

<Window x:Class="WpfApplication6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Canvas>
            <Button Width="100" Height="30" Content="Click" Click="ButtonBase_OnClick" x:Name="btn"/>
            <TextBlock Text="Click" Width="100" Height="30" Canvas.Top="40" MouseDown="UIElement_OnMouseDown" x:Name="tb"/>
        </Canvas>
    </Grid>
</Window>

And the codebehind:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Canvas.LeftProperty.OverrideMetadata(typeof(Button), new FrameworkPropertyMetadata(ButtonCallback));
        Canvas.LeftProperty.OverrideMetadata(typeof(TextBlock), new FrameworkPropertyMetadata(TextBoxCallback));
        Canvas.LeftProperty.OverrideMetadata(typeof(UIElement), new FrameworkPropertyMetadata(UIElementCallback));
    }

    private void ButtonCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Console.WriteLine("Button changed position");
    }

    private void TextBoxCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Console.WriteLine("Textbox changed position");
    }

    private void UIElementCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Console.WriteLine("UI Element changed position");
    }

    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        Canvas.SetLeft(btn, 100);
    }

    private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
    {
        Canvas.SetLeft(tb, 100);
    }
}
AkselK
  • 2,563
  • 21
  • 39