J'ai ceci:
<TabControl Margin="0,24,0,0">...</TabControl>
Je veux uniquement lier le "Top"
partie de TabControl, que je ferais intuitivement de cette façon:
<TabControl Margin="0,{Binding ElementName=TheMenu, Path=Height},0,0">
...
</TabControl>
Comment fait-on ça ?
Avez-vous essayé d'utiliser un convertisseur comme celui-ci?
dans 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
Ou en 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>
Modifier:
Utilisation d'un multi-convertisseur
Il est également possible d'obtenir les quatre valeurs pendant l'exécution et d'utiliser un MultiValueConverter. La propriété Top de l'objet Thickness n'est pas un objet de dépendance , vous ne pouvez donc pas lui définir de liaison (sauf si votre source n'est pas un objet de dépendance).
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>
... et 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;
}
}
Modifier (2) Reliure inversée:
Je ne sais pas si cela vous rendra heureux. À mon humble avis, j'essaierais d'éviter cela, mais ok ... Si votre source est une propriété de dépendance, vous pouvez la lier à la marge:
<Slider Name="Slider5" Minimum="-99" Maximum="0" Value="{Binding ElementName=TabControl, Path=Margin.Top, Mode=OneWayToSource}"></Slider>
Mais j'ai des effets avec ça.
L'astuce est que vous ne liez pas une partie de la marge de votre TabControl à "quelque chose d'autre", mais que vous liez "autre chose" à la marge de votre TabControl et spécifiez le mode de liaison OneWayToSource .
En fait, la propriété Margin
d'un contrôle est de type Thickness
. Nous pouvons donc le lier à la propriété si vous tapez l'épaisseur.
public Thickness LeftMargin { get; set; }
et Vous pouvez également définir une partie d'un objet Épaisseur. Comme -
LeftMargin = new Thickness(20,0,0,0);
et dans Xaml
nous pouvons lier cette propriété directement à la propriété margin de n'importe quel élément .. comme ceci ..
<TextBlock Text="Some Text" Margin="{Binding LeftMargin}" />
Vous pouvez essayer quelque chose comme this réponse à une autre question.
La solution utilise une propriété jointe qui permet le XAML comme suit:
<Button ap:MoreProps.MarginRight="10" />
La propriété jointe est également soutenue par un DependencyObject afin que la liaison de données fonctionne.
J'ai utilisé cette solution de contournement pour la marge gauche uniquement avec StackPanel. L'avantage est que vous n'avez besoin d'aucun convertisseur.
<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>
D'après votre code, je pense que votre menu et tabControl peuvent se chevaucher, vous voulez donc utiliser la marge pour les séparer. Je ressens cette pratique comme une disposition CSS à deux colonnes.
Pour en revenir au point, je pense que vous pouvez appliquer TranslateFransform
à TabControl.RenderTransform
. Vous pouvez lier la propriété Y
.
Pour développer la méthode de Ioop de création d'une propriété pour contrôler la marge au lieu d'un convertisseur si vous n'êtes pas attaché à un autre élément WPF:
Créez 4 propriétés standard et une propriété en lecture seule, comme so-
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
Ensuite, il vous suffit d'ajouter le XAML
-
<Label x:Name="MyLabel" Margin="{Binding Path=MyMargin, FallbackValue=0 0 0 0, Mode=OneWay}"/>
Ensuite, sur le code derrière sur la fenêtre WPF-
Private _NewMargin as New CustomMargin
Public Sub New()
InitializeComponent()
MyLabel.DataContext = _NewMargin
End Sub
À partir de là, vous pouvez utiliser le contrôle de votre choix pour modifier les 4 marges séparément et le Class
est réutilisable pour d'autres contrôles.