Подтвердить что ты не робот

Связывание только части свойства margin элемента управления WPF

У меня есть это:

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

Я хочу привязать только часть "Top" TabControl, которая интуитивно я буду делать это следующим образом:

<TabControl Margin="0,{Binding ElementName=TheMenu, Path=Height},0,0">
 ...
</TabControl>

Как мне это сделать?

4b9b3361

Ответ 1

Вы пробовали использовать такой конвертер?

в 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

Или в С#

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>

Edit:
Использование MultiConverter

Также возможно получить все четыре значения во время выполнения и использовать MultiValueConverter. Верхнее свойство объекта толщины не является объектом-зависимым, поэтому вы не можете определить привязку к нему (если ваш источник не является объектом-зависимым).

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>

... и С#

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

Изменить (2) Обратное связывание:
Я не уверен, что это сделает вас счастливыми. По моему скромному мнению, я постараюсь избежать этого, но нормально... Если ваш источник - свойство Dependency-Property, вы можете привязать его к Margin:

<Slider Name="Slider5" Minimum="-99" Maximum="0" Value="{Binding ElementName=TabControl, Path=Margin.Top, Mode=OneWayToSource}"></Slider>

Но у меня есть некоторые эффекты с этим.
Хитрость заключается в том, что вы не привязываете часть Margin вашего TabControl к "чему-то еще", а привязываете "что-то еще" к Margin вашего TabControl и указываете Binding-Mode OneWayToSource.

Ответ 2

Фактически свойство Margin элемента управления имеет тип Thickness. Поэтому мы можем привязать его к Property, если тип Thickness.

 public Thickness LeftMargin { get; set; }

и вы также можете установить часть объекта "Толщина". Как -

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

и в Xaml мы можем привязать это свойство непосредственно к свойству margin любого элемента... как это..

 <TextBlock Text="Some Text"  Margin="{Binding LeftMargin}"  />

Ответ 3

Я использовал это обходное решение для левого поля только с помощью StackPanel. Преимущество в том, что вам не нужен конвертер.

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

предварительный просмотр

Ответ 4

Вы можете попробовать что-то вроде this ответить на другой вопрос.

В решении используется связанное свойство, которое позволяет XAML следующим образом:

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

Вложенное свойство также поддерживает объект DependencyObject, поэтому привязка данных будет работать.

Ответ 5

Из вашего кода я считаю, что ваше меню и tabControl могут перекрываться, поэтому вы хотите использовать маржу для их разделения. Я чувствую эту практику, как два макета столбца CSS.

Вернемся к сути, я думаю, вы можете применить TranslateFransform к TabControl.RenderTransform. Вы можете привязать свойство Y.

Ответ 6

Чтобы расширить метод Ioop создания свойства для управления маржи вместо конвертера, если вы не привязаны к другому элементу WPF:

Создайте 4 стандартных свойства и свойство readonly, например:

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

Тогда вам просто нужно добавить XAML -

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

Затем в коде позади окна WPF -

Private _NewMargin as New CustomMargin

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

Оттуда вы можете использовать любой элемент управления, который хотите изменить все 4 поля отдельно, а Class можно использовать повторно для других элементов управления.