2011-10-18 9 views
0

初めてポストの幅と一致していません:)私はちょうど数字に見えることはできません、私のユーザーコントロールの幅で、この問題を抱えているWPFユーザーコントロールの幅が私のためにその子の水平のStackPanel

を伸ばしでる。

私はItemsControl(panleは水平StackPanelです)を含むUserControlを基本的に持っています。アイテムのDataTemplateは標準のButtonです。 私はItemsControlに文字列のリストをバインドし、各文字列はButtonのContentプロパティにバインドされます。今までうまく動作します。

私が行う必要があるのは、ItemsControl内の各単一項目(文字列内のボタン)がレンダリングされていない場合でもそれらの幅を追跡することです。私は動的に(サイズ変更中に)UserControlの最大幅を超える項目を削除し、十分なスペースがある場合にそれらを再度追加する必要があります。これを実現するために

私は次の関数を使用して、各文字列の幅を測定:

private double GetTextWidth(string text) 
    { 
     FormattedText ft = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), this.FontSize, this.Foreground); 
     ft.Trimming = TextTrimming.CharacterEllipsis; 
     return ft.WidthIncludingTrailingWhitespace; 
    } 

私は、手動でこのマージンはボタンで必要な間隔で、返された値に6のマージンを追加します。 私のList iの文字列から生成されたすべての値を集計すると、UserControlとほぼ同じ幅になるはずです。すべてのレイアウトが伸びているので(ウインドウ内のUserControlでさえ)、余白やパディングはなく(私が見る限り)、幅が1の境界線が1つしかありません。

問題これはうまくいかないということです。計算された幅に手動で大きな値(45〜65単位)を追加して、「ピクセル完全」にする必要があります。

私は明らかにこの問題の根本を見つけようとしましたが、できませんでした。 最初に私はそれがディップによって引き起こされたと思った< - >ピクセル問題ですが、そうではないようです。 私は、単一の文字列の幅と、同じ文字列を含むボタンの幅を測定しました。すべてのシナリオで、第1と第2は6単位で異なる。 ボタンの間に目に見えるスペースはありません。だから私は本当に多くのオーバーヘッドがどこから来ているのか説明できません。 FontSizeを変更すると値を変更する必要があるということがわかりましたが、それはかなり明白です...

私は何か大きなアイデアが足りないのでしょうか? 読んでいただきありがとうございます!

答えて

0

私が正しく理解していれば、画面上に完全には見えないアイテムを隠したいと思っています。

これまで、コントロールが完全に表示されているかどうかを示すヘルパーメソッドを使用してこれを行っていますが、コントロールが完全に表示されていない場合はコントロールの可視性をHiddenに設定します。私はLoadedSizeChangedイベントで実装しました。コードビハインドLoadedSizeChangedイベントは、このようなものに見えた

public enum ControlVisibility 
{ 
    Hidden, 
    Partial, 
    Full, 
    FullHeightPartialWidth, 
    FullWidthPartialHeight 
} 


/// <summary> 
/// Checks to see if an object is rendered visible within a parent container 
/// </summary> 
/// <param name="child">UI element of child object</param> 
/// <param name="parent">UI Element of parent object</param> 
/// <returns>ControlVisibility Enum</returns> 
public static ControlVisibility IsObjectVisibleInContainer(
    FrameworkElement child, UIElement parent) 
{ 
    GeneralTransform childTransform = child.TransformToAncestor(parent); 
    Rect childSize = childTransform.TransformBounds(
     new Rect(new Point(0, 0), new Point(child.Width, child.Height))); 

    Rect result = Rect.Intersect(
     new Rect(new Point(0, 0), parent.RenderSize), childSize); 

    if (result == Rect.Empty) 
    { 
     return ControlVisibility.Hidden; 
    } 
    if (result.Height == childSize.Height && result.Width == childSize.Width) 
    { 
     return ControlVisibility.Full; 
    } 
    if (result.Height == childSize.Height) 
    { 
     return ControlVisibility.FullHeightPartialWidth; 
    } 
    if (result.Width == childSize.Width) 
    { 
     return ControlVisibility.FullWidthPartialHeight; 
    } 
    return ControlVisibility.Partial; 
} 

:ここ

がレンダリングされたコントロールの可視性を返されたヘルパークラスです

ControlVisibility ctrlVisibility= 
    WPFHelpers.IsObjectVisibleInContainer(button, parent); 

if (ctrlVisibility == ControlVisibility.Full 
    || isVisible == ControlVisibility.FullWidthPartialHeight) 
{ 
    button.Visibility = Visibility.Visible; 
} 
else 
{ 
    button.Visibility = Visibility.Hidden; 
} 
+0

おかげでレイチェルを、あなたのコードは面白そうですね。問題は、ItemsControlへのアクセスが、レンダリングされたサイズを把握するために必要なボタンではなく、指定された文字列オブジェクトを返すように、子アイテムに直接アクセスできないことです(テンプレート化されているので)。 – r41n

+0

'Template'の中の' Button'の 'Loaded' /' SizeChanged'イベントの後ろに置いておきます。親を取得するには、 'ItemsControl'を名前で参照できる必要があります。動作しない場合、次のリンクにあるヘルパークラスを使用してビジュアルツリーを上に移動し、ボタンを含む 'StackPanel'を見つけることができます。 http://rachel53461.wordpress.com/2011/10/09/navigating-wpfs-visual-tree/ – Rachel

+0

魅力のように動作しますが、私があなたの説明どおりに行っていなくても、あなたの答えが私を大いに助けました。どうもありがとうございました! – r41n

関連する問題