0

I want to bind some controls' margin, let's say, a button for example:

<Window.Resources>
    <local:MarginConverter x:Key="marginConverter1"/>
</Window.Resources>

<Grid HorizontalAlignment="Left" VerticalAlignment="Top" 
      Margin="{Binding MyThickness, 
      Converter={StaticResource marginConverter1}}">
    <Button>Button1</Button>
</Grid>

According to the ref. here: SO: Binding a part of the margin, I created a MarginConverter class and a MyDataContext class to implement INotifyPropertyChanged interface (see below), but the Button1 persists in the top-left position (as if its margin is 0).

Public Class MyDataContext
   Implements INotifyPropertyChanged

   Private _myThickness As Thickness = New Thickness(20, 10, 20, 0)

   Public Event PropertyChanged As PropertyChangedEventHandler _
       Implements INotifyPropertyChanged.PropertyChanged

   Private Sub OnPropertyChanged(propertyName As String)
       RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
   End Sub

   Public Property MyThickness As Thickness
       Get
           Return _myThickness 
       End Get
       Set(value As Thickness)
           _myThickness = value
           OnPropertyChanged("MyThickness")
       End Set
   End Property
End Class

And the code behind:

Dim myDataContext1 As New MyDataContext()
Private Sub Window1_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
   myDataContext1.MyThickness = New Thickness(20, 150, 20, 0)
End Sub

Please help me to clarify my misunderstanding, even a basic knowledge or a clear explanation from you will be appreciated!

P/S: My intention for binding the top margin is when user does some specific task, a 25-height border will be appear at the top of the window, so all the existing controls must go down. So that if you have another approach, please share here. Thank you.

Community
  • 1
  • 1
nambk
  • 445
  • 3
  • 13
  • i'm not so good at VB, and you didn't supply a `marginConverter1` code, but it looks like you are try to do something on binding, that already a `Thickness` which is more than enough for binding. `Margin` have value of `Thickness`, so you need to provide binding with data of type `Thickness` or anything any other type with converter. PS if you used code from the link AS IS, this wouldn't work, bc they provide a `double` with binding and convert it to `Thickness` with converter, while you already supply a `Thickness`. – Shakra Dec 27 '16 at 05:42
  • Hi Shakra, thanks for your reply. Yes, I used the VB code of the MarginConverter class in my given SO-link. I will try to figure it out with your suggestion! – nambk Dec 27 '16 at 06:06
  • Try your code without `Converter` in Binding – Shakra Dec 27 '16 at 06:17
  • Dear @Shakra, to have only top margin value, I removed the `MarginConverter` in xaml but the button still stayed there on the top-left. I also tried to add a new property named `MyTopMargin` as `Integer` to use the Converter again, but it didn't work too. I think the issue lies somewhere else... Could you figure it out? – nambk Dec 27 '16 at 06:26

2 Answers2

1

If you only want to provide a height of 25 on top of your grid dynamically, You can do it by adding a border on top row of the grid and change its visibility to "Collapsed" to "visible".

<Grid HorizontalAlignment="Left" VerticalAlignment="Top">
    <StackPanel>
    <Border Height="25"   Visibility="Collapsed">

    </Border>
    <Button >Button1</Button>
    </StackPanel>
</Grid>
Prasanth V J
  • 1,126
  • 14
  • 32
1

Ok so here working example for you, sorry but only at C# app.xaml

  <Application.Resources>
    <ResourceDictionary>
            <viewModel:TestVM x:Key="TestVm"/>
    </ResourceDictionary>
  </Application.Resources>

ViewModel

public class TestVM : INotifyPropertyChanged
    {
        Thickness myThickness = new Thickness(20,10,20,0);

        public Thickness MyThickness
        {
            get { return myThickness; }
            set { myThickness = value; OnPropertyChanged(); }
        }




        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Window1.xaml

<Window x:Class="WPF_Test_Canvas_Chart.Windows.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_Test_Canvas_Chart.Windows"
        mc:Ignorable="d"
        DataContext="{StaticResource TestVm}"
        Title="Window1" Height="300" Width="300">
    <Grid HorizontalAlignment="Left" VerticalAlignment="Top" 
      Margin="{Binding MyThickness}">
            <Button>Button1</Button>
        </Grid>

</Window>

Window1.cs

public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            var data = this.DataContext as TestVM;
            data.MyThickness = new Thickness(100,10,20,0);
        }
    }
Shakra
  • 501
  • 2
  • 8
  • Hi Shakra. I find it hard to implement to my existing VB project. But thanks so much for your deep investigation! – nambk Dec 27 '16 at 12:06