2011-05-07 10 views
0

は、例として、このウィンドウを取る:WPFは2つの同一オブジェクトを異なる方法でレンダリングするのはなぜですか?

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" ResizeMode="NoResize" SizeToContent="WidthAndHeight" SnapsToDevicePixels="True"> 
    <Grid Width="17" Margin="1"> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 

     <RepeatButton Grid.Row="0" SnapsToDevicePixels="True"> 
      <Polyline RenderOptions.EdgeMode="Aliased" Stretch="Uniform" Margin="1" Fill="Red"> 
       <Polyline.Points> 
        <Point X="0" Y="3" /> 
        <Point X="3" Y="0" /> 
        <Point X="6" Y="3" /> 
       </Polyline.Points> 
      </Polyline> 
     </RepeatButton> 

     <RepeatButton Grid.Row="1" SnapsToDevicePixels="True"> 
      <Polyline RenderOptions.EdgeMode="Aliased" Stretch="Uniform" Margin="1" Fill="Red"> 
       <Polyline.Points> 
        <Point X="0" Y="3" /> 
        <Point X="3" Y="0" /> 
        <Point X="6" Y="3" /> 
       </Polyline.Points> 
      </Polyline> 
     </RepeatButton> 
    </Grid> 
</Window> 

アプリケーションが実行されると、一番上のRepeatButton底一方(ひいては上部三角形も底よりも大きい)よりも背が高いです。どうして?
4行の同一のRepeatButtonを作成した場合、1番目と3番目のRepeatButtonのサイズは同じで、2番目と4番目のRepeatButtonよりも大きいです。

私はこれがWPFレイアウトシステムのバグでなければならないと考えていますが、この問題を回避するにはどうすればよいですか?コンテナが大きくなるにつれて、私はRepeatButtonsと三角形をstrecthする必要があるので、固定高さを使用することはできません(問題を解決します)。私が提供した例は問題を示すために単純化されています。例のウィンドウ...)。

編集:ベンのコメントへの返信で

はい、追加のスタイルで三角形がalltogether 9pxと背の高い8pxとして(私は可能性が全く同じように通じRepeatButtonsから出てくるとだけ残してくださいグリッドの子としてのポリライン、それは同じ結果を与えるでしょう)。三角形は等しかったので、グリッド幅を17にすると実際には高さが17になります.2等分高さの三角形では十分ではありません。

実際に何をしようとしていますかNumericUpDownコントロールを作成します。私は、デフォルトでは17のスピナー幅と24のUserControl MinHeightが非常に良いように見えることがわかりました。唯一の問題は、このUserControlをGridにドロップすると、常に上の三角形が1pxを背にして見た目を台無しにするということです。どのように内部のマージンとパディングと絡み合っても、トップの三角形は常に1pxを必要以上に大きくします。だから本質的に私が望むのは、NumericUpDownを持つことです。それは、Gridに配置されたときに、それ自身を歪ませないということです。デフォルトでは、get go(グリッドなしのRowHeight = "Auto")と適切な縮尺(固定高さなし)から完全に見えるはずです。ピクセルを物理的に見ることで、すべてが与えられたディメンションにうまく収まるため、可能でなければなりません。 Result

:ここ

<UserControl x:Class="HRS.NumericUpDown" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      MinWidth="40" MinHeight="24" Name="ucNUPD" Background="White" SnapsToDevicePixels="True"> 
    <UserControl.Resources> 
     <Style TargetType="{x:Type RepeatButton}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type RepeatButton}"> 
         <Border Name="borderOuter" BorderThickness="1" BorderBrush="Red"> 
          <Border Name="borderInner" BorderThickness="1" BorderBrush="Blue"> 
           <ContentPresenter Margin="2,1" /> 
          </Border> 
         </Border> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

     <Style x:Key="triangleStyle" TargetType="{x:Type ContentControl}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="{x:Type ContentControl}"> 
         <Polyline HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Fill="Green" RenderOptions.EdgeMode="Aliased" Stretch="Uniform"> 
          <Polyline.Points> 
           <Point X="0" Y="3" /> 
           <Point X="3" Y="0" /> 
           <Point X="6" Y="3" /> 
          </Polyline.Points> 
         </Polyline> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </UserControl.Resources> 

    <Border BorderThickness="1" BorderBrush="#ABADB3"> 
     <DockPanel> 
      <UniformGrid Margin="1" DockPanel.Dock="Right" Rows="2" MinWidth="17" Width="17"> 
       <RepeatButton Name="repeatButtonUp" Grid.Row="0"> 
        <ContentControl Style="{StaticResource triangleStyle}" /> 
       </RepeatButton> 

       <RepeatButton Name="repeatButtonDown" Grid.Row="1"> 
        <ContentControl Style="{StaticResource triangleStyle}" RenderTransformOrigin="0.5, 0.5"> 
         <ContentControl.RenderTransform> 
          <ScaleTransform ScaleY="-1" /> 
         </ContentControl.RenderTransform> 
        </ContentControl> 
       </RepeatButton> 
      </UniformGrid> 

      <TextBox BorderThickness="0" VerticalContentAlignment="Center" Text="0" /> 
     </DockPanel> 
    </Border> 
</UserControl> 

は、最終結果がどのように見えるかの写真です:ここで

は、私はそれがよりコンパクトにするためにすべての非必須物事を取り除いてきました、私のNumericUpDownをあります(画像は100%に収まらないが、関連するすべての詳細を見ることができる)。

右側には、NumericUpDownsのズームインが表示されます。下の方が正しいように見えますが、グリッドの行の高さが[自動]に設定されているためです。一番上のものはゆがんでいますが、デフォルトでは下のものとまったく同じに見えます。私はちょうど実行可能な解決策を発見したかもしれない

うーん

は...:
私のNumericUpDownを中のContentPresenterのマージンを設定することにより、「3,1」は、すべてが完璧に見えるしているようです。すべてが正確にそれがすべきであるように思われるので、予備テストは非常に有望です...
私はそれにいくつかのより多くの明日をテストしますし、すべてが正しい:)としてベンの答えをマークする良い行けば

答えて

4

SizeToContent = "WidthAndHeight"の場合、グリッドの幅を17に設定すると、高さは17になります。ただし、17/2 = 8.5の場合、1行はSnapsToDevicePixels = "True"他は8ピクセル高いでしょう。幅を18に設定すると、それらは等しくなります。私の理論の

証明:あなたは9ピクセル、高さ、および8つのピクセルの一つを有するトライアングルを獲得し、このスニペットでは

<Grid Width="17" Margin="0"> 
<Grid.Resources> 
    <Style TargetType="{x:Type RepeatButton}"> 
    <Setter Property="BorderThickness" Value="0"/> 
    <Setter Property="Padding" Value="0"/> 
    <Setter Property="Margin" Value="0" /> 
    <Setter Property="Template"> 
     <Setter.Value> 
     <ControlTemplate TargetType="{x:Type ButtonBase}"> 
      <ContentPresenter Margin="0" 
           SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
     </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
    </Style> 
</Grid.Resources> 

<Grid.RowDefinitions> 
    <RowDefinition /> 
    <RowDefinition /> 
</Grid.RowDefinitions> 

<RepeatButton Grid.Row="0" SnapsToDevicePixels="True"> 
    <Polyline RenderOptions.EdgeMode="Aliased" Stretch="Uniform" Margin="0" Fill="Red"> 
    <Polyline.Points> 
     <Point X="0" Y="3" /> 
     <Point X="3" Y="0" /> 
     <Point X="6" Y="3" /> 
    </Polyline.Points> 
    </Polyline> 
</RepeatButton> 

<RepeatButton Grid.Row="1" SnapsToDevicePixels="True"> 
    <Polyline RenderOptions.EdgeMode="Aliased" Stretch="Uniform" Margin="0" Fill="Red"> 
    <Polyline.Points> 
     <Point X="0" Y="3" /> 
     <Point X="3" Y="0" /> 
     <Point X="6" Y="3" /> 
    </Polyline.Points> 
    </Polyline> 
</RepeatButton> 

は、しかし、あなたは解決策のためにしたい場合は、この方法を試してください。

<RepeatButton Grid.Row="1" SnapsToDevicePixels="True" Height="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth}" > 
    <Polyline RenderOptions.EdgeMode="Aliased" Stretch="Uniform" Margin="0" Fill="Red"> 
    <Polyline.Points> 
     <Point X="0" Y="3" /> 
     <Point X="3" Y="0" /> 
     <Point X="6" Y="3" /> 
    </Polyline.Points> 
    </Polyline> 
</RepeatButton> 

この方法で幅とボタンの高さが等しくなります。いくつかの厄介なことを行うことができます

あなたがあまりにも少ないコンバータを書くことができると思われる場合

、:

<RepeatButton Grid.Row="1" SnapsToDevicePixels="True" Height="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Converter={StaticResource TriangleWidthConverter}}" > 
    <Polyline RenderOptions.EdgeMode="Aliased" Stretch="Uniform" Margin="0" Fill="Red"> 
    <Polyline.Points> 
     <Point X="0" Y="3" /> 
     <Point X="3" Y="0" /> 
     <Point X="6" Y="3" /> 
    </Polyline.Points> 
    </Polyline> 
</RepeatButton> 

public class TriangleWidthConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
    int width = 0; 
    if (int.TryParse(value.ToString(), out width)) 
     return width + 1; // Do some fun here. 
    return value; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
    throw new NotImplementedException(); 
    } 
} 

は、私は、これらが役立つことを願っています。

+0

私はBenに同意しますが、SnapsToDevicePixels = "True"を持っているため、これが起こるもう一つの理由が追加されます。これを設定することによって、WPFは実際のピクセル境界ですべてがエッジになるようにしていることを伝えます。偶数の項目があるが奇数ピクセルなので、WPFは1つのサイズを別のサイズにしなければならない。 –

+0

@Matt Westあなたは本当ですが、MarkoはSnapsToDevicePixelsが何をしているか知っているので、彼はほとんどすべてを設定しています。 :) – Ben

+0

幅を18に設定すると、両方の三角形のサイズが同じになります。しかし、私が同意しないのは、幅が17であるから高さも17になるからです。実際には、最初のRepeatButtonは13pxの高さで出てきて、2番目の高さは12pxです。奇妙なことは、両方のポリラインからStretch = "Uniform"を単に削除すると、両方とも12pxの高さになります。私はSnapToDevicePixelsを純粋にこの半画素の丸めの問題を解消するために設定しました。すべての要素からプロパティを削除すると、下のボタンが大きくなります。 – Marko

0

ない考えあなたはこの動作を見ているが、これはそれを修正するために働くかもしれない理由:それぞれの上に高さを設定してみてください行数が2行の場合は.5 *、行数が4行の場合は0.25 *、行数が10行の場合は.1 *になります。

+0

2行の行の高さを.5 *に設定しても効果はありません。 – Marko

関連する問題