Wiążąca tylko część właściwości marginesu kontroli WPF

Mam to:

<TabControl Margin="0,24,0,0">...</TabControl>

Chcę związać tylko "Top" część TabControl, którą intuicyjnie zrobiłbym w ten sposób:

<TabControl Margin="0,{Binding ElementName=TheMenu, Path=Height},0,0">
 ...
</TabControl>
Jak to zrobić ?
Author: herohuyongtao, 2011-06-06

6 answers

Próbowałeś użyć takiego konwertera?

W VB.Net

Public Class MarginConverter
  Implements IValueConverter

  Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
    Return New Thickness(0, CDbl(value), 0, 0)
  End Function

  Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
    Return Nothing
  End Function
End Class

Lub w C #

public class MarginConverter : IValueConverter
{

    public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return new Thickness(0, System.Convert.ToDouble(value), 0, 0);
    }

    public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

XAML

<Window.Resources>
    <local:MarginConverter x:Key="marginConverter"></local:MarginConverter>
</Window.Resources>
<Grid>
    <StackPanel>
        <Slider Name="Slider1"></Slider>
        <TabControl Name="TabControl" Margin="{Binding ElementName=Slider1, Path=Value, Converter={StaticResource marginConverter}}">
            <Button>Some content</Button>
        </TabControl>
    </StackPanel>
</Grid>

Edytuj:
Korzystanie z Multiconvertera

Możliwe jest również uzyskanie wszystkich czterech wartości w czasie wykonywania i użycie Multivalueconvertera. Top-właściwość Thickness-Object nie jest zależnością-Object, dlatego nie możesz zdefiniować powiązania z nim (chyba że twoje źródło nie jest Dependency-Object).

XAML

<Window.Resources>
    <local:MarginConverter x:Key="marginConverter"></local:MarginConverter>
    <local:MultiMarginConverter x:Key="multiMarginConverter"></local:MultiMarginConverter>
</Window.Resources>
<Grid>
    <StackPanel>
        <Slider Name="Slider1"></Slider>
        <Slider Name="Slider2"></Slider>
        <Slider Name="Slider3"></Slider>
        <Slider Name="Slider4"></Slider>
        <TabControl Name="TabControl">
            <TabControl.Margin>
                <MultiBinding Converter="{StaticResource multiMarginConverter}">
                    <Binding ElementName="Slider1" Path="Value"></Binding>
                    <Binding ElementName="Slider2" Path="Value"></Binding>
                    <Binding ElementName="Slider3" Path="Value"></Binding>
                    <Binding ElementName="Slider4" Path="Value"></Binding>
                </MultiBinding>
            </TabControl.Margin>
            <Button>Some content</Button>
        </TabControl>
    </StackPanel>
</Grid>

... i c #

  class MultiMarginConverter : IMultiValueConverter
  {
    public object Convert(object[] values, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      return new Thickness(System.Convert.ToDouble(values[0]),
                           System.Convert.ToDouble(values[1]),
                           System.Convert.ToDouble(values[2]),
                           System.Convert.ToDouble(values[3]));
    }

    public object[] ConvertBack(object value, System.Type[] targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      return null;
    }
  }

Edit (2) Reverse-Binding:
Nie jestem pewien, czy to cię uszczęśliwi. Moim skromnym zdaniem starałbym się tego uniknąć, ale ok... Jeśli twoje źródło jest właściwością zależności, możesz powiązać to z marginesem:

<Slider Name="Slider5" Minimum="-99" Maximum="0" Value="{Binding ElementName=TabControl, Path=Margin.Top, Mode=OneWayToSource}"></Slider>
/ Align = "left" /
Sztuczka polega na tym, że nie przywiązujesz części marginesu TabControl do "czegoś innego", ale wiążesz "coś innego" na marginesie TabControl i określ tryb wiązania OneWayToSource.
 47
Author: Markus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-06 13:09:39

Właściwie Margin właściwość kontrolki jest typu Thickness. Więc możemy powiązać go z właściwością, jeśli grubość typu.

 public Thickness LeftMargin { get; set; }

I możesz też ustawić część obiektu grubości. Like -

 LeftMargin = new Thickness(20,0,0,0);

I w Xaml możemy powiązać tę właściwość bezpośrednio z właściwością margin dla dowolnego elementu..w ten sposób..

 <TextBlock Text="Some Text"  Margin="{Binding LeftMargin}"  />
 21
Author: loop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-26 23:29:05

Użyłem tego obejścia dla lewego marginesu tylko z StackPanel. Zaletą jest to, że nie potrzebujesz żadnego konwertera.

<DockPanel VerticalAlignment="Top">
  <TextBlock Name="tbkFulltextCaption"
             Text="Static Caption:"
             DockPanel.Dock="Left" />
  <StackPanel Orientation="Horizontal"
              DockPanel.Dock="Bottom">
      <FrameworkElement Name="feLeftMargin"
                        Width="{Binding Width, ElementName=tbkFulltextCaption, Mode=OneWay}" />
      <TextBlock Text="(some text with margin of tbkFulltextCaption.Width)"
                 Name="tbkUnderNonsense" 
                 FontSize="8"                                       
                 Foreground="Gray">
      </TextBlock>
  </StackPanel>
  <TextBox Name="tbFulltextSearch" />
</DockPanel>

Preview

 3
Author: adaraz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-27 13:10:00

Możesz spróbować czegoś takiego jak Ta odpowiedź z innego pytania.

Rozwiązanie wykorzystuje dołączoną właściwość, która pozwala na XAML w następujący sposób:

<Button ap:MoreProps.MarginRight="10" />

Dołączona właściwość jest również wspierana przez DependencyObject, więc powiązanie danych będzie działać.

 2
Author: bugged87,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:30:52

Z twojego kodu wnioskuję, że Twoje menu i tab control mogą się nakładać, więc chcesz użyć marginesu, aby je rozdzielić. Czuję tę praktykę jak dwukolumnowy układ CSS.

Wracając do tematu, myślę, że możesz zastosować TranslateFransform do TabControl.RenderTransform. Możesz powiązać Y właściwość.

 2
Author: Gqqnbig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-28 12:10:23

Aby rozwinąć metodę ioop polegającą na stworzeniu właściwości kontrolującej margines zamiast konwertera, jeśli nie dołączasz do innego elementu WPF:

Utwórz 4 standardowe właściwości i właściwość readonly, jak tak-

Public Class CustomMargin
    Implements INotifyPropertyChanged

    Private _Left As Double
    Private _Right As Double
    Private _Up As Double
    Private _Down As Double

    Public Sub New()
      _Up = 0
      _Down = 0
      _Left = 0
      _Right = 0
    End Sub

    Public Sub New(Vertical as Double, Horizontal as Double)
      _Up = Vertical
      _Down = Vertical
      _Left = Horizontal
      _Right = Horizontal
    End Sub

    Public Sub New(Left as Double, Up as Double, Right as Double, Down as Double)
      _Up = Up
      _Down = Down
      _Left = Left
      _Right = Right
    End Sub

    Public Property Left As Double
        Get
            Return _Left
        End Get
        Set(value As Double)
            _Left = value
            OnPropertyChanged(New PropertyChangedEventArgs("MyMargin"))
        End Set
    End Property

    Public Property Right As Double
        Get
            Return _Right
        End Get
        Set(value As Double)
            _Right = value
            OnPropertyChanged(New PropertyChangedEventArgs("MyMargin"))
        End Set
    End Property

    Public Property Up As Double
        Get
            Return _Up
        End Get
        Set(value As Double)
            _Up = value
            OnPropertyChanged(New PropertyChangedEventArgs("MyMargin"))
        End Set
    End Property

    Public Property Down As Double
        Get
            Return _Down
        End Get
        Set(value As Double)
            _Down = value
            OnPropertyChanged(New PropertyChangedEventArgs("MyMargin"))
        End Set
    End Property

    Public ReadOnly Property MyMargin As Thickness
        Get
            Return New Thickness(Left, Up, Right, Down)
        End Get
    End Property

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Public Sub OnPropertyChanged(ByVal e As PropertyChangedEventArgs)
        If Not PropertyChangedEvent Is Nothing Then
            RaiseEvent PropertyChanged(Me, e)
        End If
    End Sub
End Class

Następnie wystarczy dodać XAML-

<Label x:Name="MyLabel" Margin="{Binding Path=MyMargin, FallbackValue=0 0 0 0, Mode=OneWay}"/>

Następnie na kod za oknem WPF -

Private _NewMargin as New CustomMargin

Public Sub New()
  InitializeComponent()
  MyLabel.DataContext = _NewMargin
End Sub

Stamtąd możesz użyć dowolnego kontrolera, aby zmienić wszystkie 4 marginesy osobno, a {[4] } jest wielokrotnego użytku dla innych kontrolek.

 1
Author: ARidder101,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-23 16:31:09