Я предлагаю сделать это с Behavior.I'm добавив пример с MenuItem, но это то же самое для любого элемента управления с PopUp (как ComboBox)
На вашем Xaml добавить поведение прикрепить к пункту меню:
<Menu>
<MenuItem ItemsSource="{Binding GlanceOptions, Mode=OneWay}">
<interactivity:Interaction.Behaviors>
<behaviors:MenueItemSubMenuPlacementBehavior />
</interactivity:Interaction.Behaviors>
<MenuItem.Header>
<Border
Cursor="Arrow"
BorderThickness="1,1,1,0" >
<Path x:Name="DropDownIcon"
VerticalAlignment="Center"
Data="M0,0L2,3 4,0z"
/>
</Border>
</MenuItem.Header>
</MenuItem >
</Menu>
поведение Код:
public class MenueItemSubMenuPlacementBehavior : Behavior<MenuItem>
{
private PlacementMode _previousPlacementMode;
private CustomPopupPlacementCallback _previousCallback;
private Popup _menuItemPopUp;
protected override void OnAttached()
{
base.OnAttached();
Initialize();
}
private void Initialize()
{
if (AssociatedObject == null)
return;
if (_menuItemPopUp == null)
{
_menuItemPopUp = AssociatedObject?.Template?.FindName("PART_Popup", AssociatedObject) as Popup;
if (_menuItemPopUp == null)
{
AssociatedObject.Loaded -= AssociatedObject_Loaded;
AssociatedObject.Loaded += AssociatedObject_Loaded;
return;
}
_previousPlacementMode = _menuItemPopUp.Placement;
_previousCallback = _menuItemPopUp.CustomPopupPlacementCallback;
_menuItemPopUp.Placement = PlacementMode.Custom;
_menuItemPopUp.CustomPopupPlacementCallback = CustomPopupPlacementCallback;
}
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
AssociatedObject.Loaded -= AssociatedObject_Loaded;
if (_menuItemPopUp != null)
return;
_menuItemPopUp = VisualTreeHelpers.FindFirstChild<Popup>(AssociatedObject) as Popup;
if (_menuItemPopUp == null)
return;
_previousPlacementMode = _menuItemPopUp.Placement;
_previousCallback = _menuItemPopUp.CustomPopupPlacementCallback;
_menuItemPopUp.Placement = PlacementMode.Custom;
_menuItemPopUp.CustomPopupPlacementCallback = CustomPopupPlacementCallback;
}
protected override void OnDetaching()
{
base.OnDetaching();
if(AssociatedObject != null)
{
AssociatedObject.Loaded -= AssociatedObject_Loaded;
}
if (_menuItemPopUp != null)
{
_menuItemPopUp.Placement = _previousPlacementMode;
_menuItemPopUp.CustomPopupPlacementCallback = _previousCallback;
_previousCallback = null;
}
}
private CustomPopupPlacement[] CustomPopupPlacementCallback(Size popupSize, Size targetSize, Point offset)
{
var rightPlacedPopupX = offset.X;
var rightPlacedPopupY = offset.Y + (AssociatedObject.ActualHeight * YourLogic);
return new[]
{
new CustomPopupPlacement(new Point(rightPlacedPopupX, rightPlacedPopupY), PopupPrimaryAxis.Horizontal),
};
}
}
Эта нить может помочь: http://stackoverflow.com/questions/5340640/wpf-combobox-popup-placement-bottom-and-aligned-to-the-right -edge – geostocker
Я наткнулся на эту тему, когда искал, но не добился того, что искал. – TheOne
Любые идеи парней? – TheOne