感謝@Justin XL和@ grek40幫助我這麼多。
我必須爲我那可憐的英語道歉,這讓每個人都很煩惱。
我想我需要改進這個問題來幫助其他人。如何創建一個方形按鈕?
我的計劃是,不同的設備有不同的窗口大小全屏程序。
所以我的方形按鈕應該可以調整大小beaucase我想做一個Reactive用戶界面。
現在我該如何製作方形按鈕?
謝謝。
感謝@Justin XL和@ grek40幫助我這麼多。
我必須爲我那可憐的英語道歉,這讓每個人都很煩惱。
我想我需要改進這個問題來幫助其他人。如何創建一個方形按鈕?
我的計劃是,不同的設備有不同的窗口大小全屏程序。
所以我的方形按鈕應該可以調整大小beaucase我想做一個Reactive用戶界面。
現在我該如何製作方形按鈕?
謝謝。
使用Rectangle.Stretch
屬性:
<Rectangle Fill="Red" Stretch="Uniform"></Rectangle>
我覺得這回答創建一個矩形,其中寬度和高度是相同的,矩形拉伸到可用空間的實際問題。
在約束力的條款,雙方Width
和Height
一個MultiBinding
與IMultiValueConverter
實現,返回最小的所有輸入值可能會奏效。但是,它僅僅用於不提供自動伸展的控件。
可以使用附加屬性來設置相同的寬度/高度對於給定的限制:
public static class SquareSize
{
public static double GetWidthLimit(DependencyObject obj)
{
return (double)obj.GetValue(WidthLimitProperty);
}
public static void SetWidthLimit(DependencyObject obj, double value)
{
obj.SetValue(WidthLimitProperty, value);
}
public static readonly DependencyProperty WidthLimitProperty = DependencyProperty.RegisterAttached(
"WidthLimit", typeof(double), typeof(SquareSize),
new FrameworkPropertyMetadata(double.PositiveInfinity, new PropertyChangedCallback(OnWidthLimitChanged)));
private static void OnWidthLimitChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UpdateSize(d, (double)e.NewValue, GetHeightLimit(d));
}
public static double GetHeightLimit(DependencyObject obj)
{
return (double)obj.GetValue(HeightLimitProperty);
}
public static void SetHeightLimit(DependencyObject obj, double value)
{
obj.SetValue(HeightLimitProperty, value);
}
public static readonly DependencyProperty HeightLimitProperty = DependencyProperty.RegisterAttached(
"HeightLimit", typeof(double), typeof(SquareSize),
new FrameworkPropertyMetadata(double.PositiveInfinity, new PropertyChangedCallback(OnHeightLimitChanged)));
private static void OnHeightLimitChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UpdateSize(d, GetWidthLimit(d), (double)e.NewValue);
}
private static void UpdateSize(DependencyObject d, double widthLimit, double heightLimit)
{
double resultSize = Math.Min(widthLimit, heightLimit);
d.SetCurrentValue(FrameworkElement.WidthProperty, resultSize);
d.SetCurrentValue(FrameworkElement.HeightProperty, resultSize);
}
}
使用具有適當的xmlns命名空間
<Border x:Name="border" Grid.Column="1" Grid.Row="1">
<Rectangle
Fill="Red"
local:SquareSize.WidthLimit="{Binding ElementName=border,Path=ActualWidth}"
local:SquareSize.HeightLimit="{Binding ElementName=border,Path=ActualHeight}"/>
</Border>
涉及的溶液自定義控件作爲方形內容的包裝:
public class SquareContentControl : ContentControl
{
protected override Size ArrangeOverride(Size arrangeBounds)
{
var sizeLimit = Math.Min(arrangeBounds.Width, arrangeBounds.Height);
if (VisualChildrenCount > 0)
{
var child = GetVisualChild(0) as UIElement;
if (child != null)
{
child.Arrange(new Rect(new Point((arrangeBounds.Width - sizeLimit)/2, (arrangeBounds.Height - sizeLimit)/2), new Size(sizeLimit, sizeLimit)));
return arrangeBounds;
}
}
return base.ArrangeOverride(arrangeBounds);
}
protected override Size MeasureOverride(Size constraint)
{
var sizeLimit = Math.Min(constraint.Width, constraint.Height);
if (VisualChildrenCount > 0)
{
var child = GetVisualChild(0) as UIElement;
if (child != null)
{
child.Measure(new Size(sizeLimit, sizeLimit));
return child.DesiredSize;
}
}
return base.MeasureOverride(constraint);
}
}
用法:
<Border x:Name="border" Grid.Column="1" Grid.Row="1">
<local:SquareContentControl>
<Rectangle Fill="Red"/>
</local:SquareContentControl>
</Border>
設置Stretch =「Uniform」工程,但會出現一個新問題。每當設置HorizontalAlignment中心時,Rectangle HorizontalAlignment不是中心,只要將Rectangle的寬度設置爲零即可。 –
正如你所說,也許我需要了解更多關於IMultiValueConverter來實現這個目標。哈哈 –
@MelonNG問題似乎是,'Stretch =「Uniform」'目標是'Fill'內容而不是'Rectangle'本身。我可以使用信息編輯如何集中背景/填充內容,但這對其他類型的內容無幫助 - 如果您提供更多信息,我可能會有其他解決方案。 – grek40
編輯2017年8月17日僅適用於WPF,不UWP。
使用最小變換器:
public class MinConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double result = double.NaN;
if (values != null)
{
try
{
result = values.Cast<double>().Aggregate(double.PositiveInfinity, (a, b) => Math.Min(a, b));
}
catch (Exception)
{
result = double.NaN;
}
}
return result;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
然後在你的XAML設置矩形高度符合父母的邊境敏(的ActualHeight,ActualWidth的)。和矩形寬度可以直接綁定到矩形的的ActualHeight
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.1*"></RowDefinition>
<RowDefinition Height="0.8*"></RowDefinition>
<RowDefinition Height="0.1*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.1*"></ColumnDefinition>
<ColumnDefinition Width="0.8*"></ColumnDefinition>
<ColumnDefinition Width="0.1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border x:Name="Bd" Grid.Column="1" Grid.Row="1">
<Rectangle x:Name="R"
Width="{Binding Path=ActualHeight, Mode=OneWay, RelativeSource={RelativeSource Self}}">
<Rectangle.Height>
<MultiBinding Converter="converter:MinConverter">
<Binding ElementName="Bd" Path="ActualHeight"/>
<Binding ElementName="Bd" Path="ActualWidth"/>
</MultiBinding>
</Rectangle.Height>
</Rectangle>
</Border>
</Grid>
問題已經更新了,你確定你的'MultiBinding'與UWP一起工作,即使這個問題被明確否定嗎? – grek40
謝謝你的幫忙sir.But as grek40 said,microsoft已經取消了UWP中的MultiBinding。 –
這是完全正常的,有一個像這樣純 UI邏輯住其內部的代碼隱藏。我甚至會爭辯說在大多數情況下它更有效率。
在您的例子,它的超級容易用下面的代碼方你Rectangle
XAML
<Border x:Name="MyBorder"
Grid.Column="1"
Grid.Row="1"
SizeChanged="MyBorder_SizeChanged">
<Rectangle x:Name="MyRectangle"
Fill="LightBlue" />
</Border>
代碼隱藏
private void MyBorder_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (MyBorder.ActualWidth > MyBorder.ActualHeight)
{
MyRectangle.Width = MyRectangle.Height = MyBorder.ActualHeight;
}
else if (MyBorder.ActualWidth < MyBorder.ActualHeight)
{
MyRectangle.Height = MyRectangle.Height = MyBorder.ActualWidth;
}
}
但是我們可以改進嗎?既然你想要一個正方形Button
,那麼創建一個SquareButton
並將其直接插入到Grid
是最有意義的。
所以XAML可以簡化爲一個更可讀的版本低於
<local:SquareButton Grid.Column="1" Grid.Row="1" />
然後你只需要執行類似下面的
SquareButton
類
[TemplatePart(Name = PART_Root, Type = typeof(Border))]
[TemplatePart(Name = PART_ContentHost, Type = typeof(Border))]
public sealed class SquareButton : Button
{
private const string PART_Root = "Root";
private const string PART_ContentHost = "ContentHost";
public SquareButton()
{
DefaultStyleKey = typeof(SquareButton);
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
var root = (Border)GetTemplateChild(PART_Root);
var contentHost = (Border)GetTemplateChild(PART_ContentHost);
root.SizeChanged += (s, e) =>
{
if (root.ActualWidth > root.ActualHeight)
{
contentHost.Width = contentHost.Height = root.ActualHeight;
}
else if (root.ActualWidth < root.ActualHeight)
{
contentHost.Height = contentHost.Height = root.ActualWidth;
}
};
}
}
自定義控件
SquareButton
內部樣式Themes/Generic.xaml
<Style TargetType="local:SquareButton">
<Setter Property="Background"
Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
<Setter Property="Foreground"
Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
<Setter Property="BorderBrush"
Value="{ThemeResource SystemControlForegroundTransparentBrush}" />
<Setter Property="BorderThickness"
Value="{ThemeResource ButtonBorderThemeThickness}" />
<Setter Property="Padding"
Value="8,4,8,4" />
<Setter Property="HorizontalAlignment"
Value="Stretch" />
<Setter Property="VerticalAlignment"
Value="Stretch" />
<Setter Property="FontFamily"
Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontWeight"
Value="Normal" />
<Setter Property="FontSize"
Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="UseSystemFocusVisuals"
Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:SquareButton">
<Border x:Name="Root">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="ContentHost" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<PointerUpThemeAnimation Storyboard.TargetName="ContentHost" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentHost"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlHighlightTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlHighlightBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<PointerDownThemeAnimation Storyboard.TargetName="ContentHost" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentHost"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource SystemControlDisabledTransparentBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="ContentHost" Background="{TemplateBinding Background}">
<ContentPresenter x:Name="ContentPresenter"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTransitions="{TemplateBinding ContentTransitions}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw" />
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
希望這會有所幫助!
這是我需要的!哇! –
我只是編輯問題並更正要求。感謝您的幫助。 –
爲什麼你必須使用綁定?在代碼隱藏中這麼做很簡單。 –
@JustinXL我想做一個ReactiveUI,我覺得綁定是最好的選擇。如果有更好的選擇,你能幫我嗎?謝謝。 –
請參閱下面的答案。順便說一句,我認爲你應該用下面的一些評論來更新你的問題,你真正想要的是一個方形按鈕,但是你的標題和內容沒有提到它。 –