仅绑定 WPF 控件的部分边距属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6249518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Binding only part of the margin property of WPF control
提问by Tar
I have this:
我有这个:
<TabControl Margin="0,24,0,0">...</TabControl>
I want to bind only the "Top"
part of the TabControl, which intuitively I would do it this way:
我只想绑定"Top"
TabControl的一部分,直觉上我会这样做:
<TabControl Margin="0,{Binding ElementName=TheMenu, Path=Height},0,0">
...
</TabControl>
How do I do it ?
我该怎么做 ?
采纳答案by Markus
Have you tried using a converter like this?
您是否尝试过使用这样的转换器?
in VB.Net
在 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
Or in C#
或者在 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
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:
Using a MultiConverter
编辑:
使用 MultiConverter
It is also possible to get all four values during run-time and use a MultiValueConverter. The Top-Property of the Thickness-Object is not a Dependency-Object, therefor you can't define a binding to it (unless your source is not a Dependency-Object).
还可以在运行时获取所有四个值并使用 MultiValueConverter。Thickness-Object 的 Top-Property 不是 Dependency-Object,因此您无法定义到它的绑定(除非您的源不是 Dependency-Object)。
XAML
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>
... and c#
...和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:
I'm not sure if this will make you happy. In my humble opinion I would try to avoid this, but ok... If your source is a Dependency-Property, you can bind this to the Margin:
编辑(2)反向绑定:
我不确定这是否会让你开心。以我的拙见,我会尽量避免这种情况,但是好吧......如果你的来源是一个依赖属性,你可以将它绑定到边距:
<Slider Name="Slider5" Minimum="-99" Maximum="0" Value="{Binding ElementName=TabControl, Path=Margin.Top, Mode=OneWayToSource}"></Slider>
But I've got some effects with this.
The trick is, that you do not bind a part of the Margin of your TabControl to "something else", but bind "something else" to the Margin of your TabControl and specify Binding-Mode OneWayToSource.
但我对此有一些影响。
诀窍是,您不将 TabControl 的 Margin 的一部分绑定到“其他东西”,而是将“其他东西”绑定到 TabControl 的 Margin 并指定 Binding-Mode OneWayToSource。
回答by loop
Actually Margin
property of a control is of Thickness
Type. So we can bind it to Property if type Thickness.
实际上Margin
控件的属性是Thickness
类型。所以我们可以将它绑定到 Property if type Thickness。
public Thickness LeftMargin { get; set; }
and You can set a part of a Thickness object too. Like -
并且您也可以设置厚度对象的一部分。喜欢 -
LeftMargin = new Thickness(20,0,0,0);
and in Xaml
we can bind this property directly to margin property of any element..like this..
并且Xaml
我们可以直接将此属性绑定到任何元素的边距属性..像这样..
<TextBlock Text="Some Text" Margin="{Binding LeftMargin}" />
回答by bugged87
You could try something like thisanswer from another question.
你可以从另一个问题尝试类似这个答案。
The solution uses an attached property that allows for XAML like the following:
该解决方案使用允许 XAML 的附加属性,如下所示:
<Button ap:MoreProps.MarginRight="10" />
The attached property is also backed by a DependencyObject so data binding will work.
附加属性也由 DependencyObject 支持,因此数据绑定将起作用。
回答by Gqqnbig
From your code, I figure that your menu and tabControl may overlap, so you want to use margin to separate them. I feel this practice like two Column CSS Layout.
从您的代码中,我认为您的菜单和 tabControl 可能重叠,因此您想使用边距将它们分开。我觉得这种做法就像两列 CSS 布局。
Back to the point, I think you can apply TranslateFransform
to TabControl.RenderTransform
. You can bind Y
property.
回到一点,我觉得你可以申请TranslateFransform
到TabControl.RenderTransform
。您可以绑定Y
属性。
回答by adaraz
I have used this workaround for left margin only with StackPanel. Benefit is that you don't need any Converter.
我仅在 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>
回答by ARidder101
To expand on Ioop's method of making a property to control margin instead of a converter if you aren't attaching to another WPF element:
如果您没有附加到另一个 WPF 元素,要扩展 Ioop 的方法来控制边距而不是转换器:
Create 4 standard properties and a readonly property, like so-
创建 4 个标准属性和一个只读属性,如下所示-
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
Then you just have to add the XAML
-
然后你只需要添加XAML
-
<Label x:Name="MyLabel" Margin="{Binding Path=MyMargin, FallbackValue=0 0 0 0, Mode=OneWay}"/>
Then on the code behind on the WPF window-
然后在 WPF 窗口后面的代码上-
Private _NewMargin as New CustomMargin
Public Sub New()
InitializeComponent()
MyLabel.DataContext = _NewMargin
End Sub
From there you can use whatever control you desire to change all 4 margins separately and the Class
is reusable for other controls.
从那里您可以使用任何您想要分别更改所有 4 个边距的Class
控件,并且该控件可重用于其他控件。
回答by Athanviel
Ok it is old, but I was searching for a nicer way:
好的,它很旧,但我正在寻找更好的方法:
<TabControl>
<TabControl.Margin>
<Thickness Top="{Binding ElementName=TheMenu, Path=Height}" />
</TabControl.Margin>
</TabControl>