どのように私は、リストボックスの右側にエキスパンダーを固定できますか?
質問
以下のXAMLコードは、私がパンダボタンはリストボックスとグリッドの間になりたい除いて正常に動作します。私が設定されている場合ExpandDirection =「左」ボタンは、リストボックスとグリッドの間ですが、ボタンの方向指示器は、ユーザーに混乱している - 拡張したときには、右を指し、それが展開されていないときには、左を指しています。私は、方向指示器がExpandDirection =「右」それがないように動作するようにしたいが、私はExpandDirection =「左」の機能が欲しいます。
<DockPanel>
<Expander ExpandDirection="Right">
<ListBox>
<ListBoxItem>Item One</ListBoxItem>
<ListBoxItem>Item Two</ListBoxItem>
<ListBoxItem>Item Three</ListBoxItem>
<ListBoxItem>Item Four</ListBoxItem>
<ListBoxItem>Item Five</ListBoxItem>
</ListBox>
</Expander>
<Grid Background="AliceBlue">
<TextBlock >
Other Content
</TextBlock>
</Grid>
</DockPanel>
解決
「ExpanderLeftHeaderStyle」に「ExpanderRightHeaderStyle」と「ExpanderRightHeaderStyle」を「ExpanderLeftHeaderStyleを」名前の変更、テンプレートのXAMLに行き、パンダの現在のテンプレートのコピーを編集し、Expression Blendのに使用します。
他のヒント
私は(コードが以下に含まれる)バックしばらく書いDockedExpanderクラスを使用することを好みます。このクラスは、自動的にそれがドッキングされているDockPanelのどんな側面のために自分自身を設定します。
たとえば、で
<DockPanel>
<edf:DockedExpander DockPanel.Dock="Left">
<ListBox ...
</edf:DockedExpander>
<Grid ...
</DockPanel>
エクスパンダは、正しい道に直面してボタンで、左から開きます。しかし、それを変更します:
<edf:DockedExpander DockPanel.Dock="Right">
自動的に一致するように、エキスパンダーの残りの部分を調整します。 「トップ」および「ボトム」ドッキングます。
と同じ 私のプロジェクトにWPFの内部コードの数百行をコピーするという考えは私に忌まわしいだったので私はDockedExpanderを実装しました。それはWPFの内部スタイルを読み取るためにも、私のDockedExpander制御は、自動的に新しいテーマのスタイルに適応します。
ここでDockedExpanderクラスのコードがあります:
public class DockedExpander : Expander
{
static DockedExpander()
{
_directions = new Dictionary<Dock, DirectionData>();
_directions[Dock.Left] = new DirectionData { Reverse = Dock.Right, ExpandDirection = ExpandDirection.Right };
_directions[Dock.Right] = new DirectionData { Reverse = Dock.Left, ExpandDirection = ExpandDirection.Left };
_directions[Dock.Top] = new DirectionData { Reverse = Dock.Bottom, ExpandDirection = ExpandDirection.Down };
_directions[Dock.Bottom] = new DirectionData { Reverse = Dock.Top, ExpandDirection = ExpandDirection.Up };
DockPanel.DockProperty.OverrideMetadata(typeof(DockedExpander), new FrameworkPropertyMetadata
{
PropertyChangedCallback = (obj, e) => ((DockedExpander)obj).UpdateExpandDirection()
});
ExpandDirectionProperty.OverrideMetadata(typeof(DockedExpander), new FrameworkPropertyMetadata
{
PropertyChangedCallback = (obj, e) => { throw new ArgumentException("Cannot set ExpandDirection because DockedExpander always computes its ExpandDirection from the DockPanel.Dock property"); }
});
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
UpdateExpandDirection();
}
private void UpdateExpandDirection()
{
// Can't use GetTemplateChild because non-PART_ names are not guaranteed to stay the same
var dockPanel = FindTwoElementDockPanelUnder(this);
var headerSite = dockPanel.Children[0];
var expandSite = dockPanel.Children[1];
// Compute the docking
Dock myDock = DockPanel.GetDock(this);
DirectionData myDockData = _directions[myDock];
DockPanel.SetDock(headerSite, myDockData.Reverse);
DockPanel.SetDock(expandSite, myDock);
headerSite.SetValue(FrameworkElement.StyleProperty, myDockData.HeaderSiteStyle);
}
private static Dictionary<Dock, DirectionData> _directions;
private class DirectionData
{
public Dock Reverse;
public ExpandDirection ExpandDirection;
public Style HeaderSiteStyle
{
get
{
if(_headerSiteStyle==null)
{
var expander = new Expander { ExpandDirection = this.ExpandDirection };
expander.BeginInit();
expander.EndInit();
expander.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
var headerSite = FindTwoElementDockPanelUnder(expander).Children[0];
_headerSiteStyle = ((FrameworkElement)headerSite).Style;
}
return _headerSiteStyle;
}
}
private Style _headerSiteStyle;
}
private static DockPanel FindTwoElementDockPanelUnder(DependencyObject visual)
{
while(true)
switch(VisualTreeHelper.GetChildrenCount(visual))
{
case 1: visual = VisualTreeHelper.GetChild(visual, 0); continue;
case 2: return visual as DockPanel;
default: return null;
}
}
}
いつものように、カスタムコントロールを使用できるようにあなたのXAML名前空間宣言(のxmlns)が必要です。