2017-08-15 328 views
0

感謝@Justin XL和@ grek40幫助我這麼多。
我必須爲我那可憐的英語道歉,這讓每個人都很煩惱。
我想我需要改進這個問題來幫助其他人。如何創建一個方形按鈕?

這裏是最新的:
我需要做一個方形按鈕這樣的: enter image description here


我的計劃是,不同的設備有不同的窗口大小全屏程序。
所以我的方形按鈕應該可以調整大小beaucase我想做一個Reactive用戶界面。
現在我該如何製作方形按鈕?
謝謝。

+0

爲什麼你必須使用綁定?在代碼隱藏中這麼做很簡單。 –

+0

@JustinXL我想做一個ReactiveUI,我覺得綁定是最好的選擇。如果有更好的選擇,你能幫我嗎?謝謝。 –

+0

請參閱下面的答案。順便說一句,我認爲你應該用下面的一些評論來更新你的問題,你真正想要的是一個方形按鈕,但是你的標題和內容沒有提到它。 –

回答

2

使用Rectangle.Stretch屬性:

<Rectangle Fill="Red" Stretch="Uniform"></Rectangle> 

我覺得這回答創建一個矩形,其中寬度和高度是相同的,矩形拉伸到可用空間的實際問題。

在約束力的條款,雙方WidthHeight一個MultiBindingIMultiValueConverter實現,返回最小的所有輸入值可能會奏效。但是,它僅僅用於不提供自動伸展的控件。


可以使用附加屬性來設置相同的寬度/高度對於給定的限制:

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

設置Stretch =「Uniform」工程,但會出現一個新問題。每當設置Horizo​​ntalAlignment中心時,Rectangle Horizo​​ntalAlignment不是中心,只要將Rectangle的寬度設置爲零即可。 –

+0

正如你所說,也許我需要了解更多關於IMultiValueConverter來實現這個目標。哈哈 –

+0

@MelonNG問題似乎是,'Stretch =「Uniform」'目標是'Fill'內容而不是'Rectangle'本身。我可以使用信息編輯如何集中背景/填充內容,但這對其他類型的內容無幫助 - 如果您提供更多信息,我可能會有其他解決方案。 – grek40

1

編輯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> 
+0

問題已經更新了,你確定你的'MultiBinding'與UWP一起工作,即使這個問題被明確否定嗎? – grek40

+0

謝謝你的幫忙sir.But as grek40 said,microsoft已經取消了UWP中的MultiBinding。 –

3

這是完全正常的,有一個像這樣 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> 

希望這會有所幫助!

+1

這是我需要的!哇! –

+0

我只是編輯問題並更正要求。感謝您的幫助。 –

相關問題