Skip to content

Commit

Permalink
Merge pull request #31 from gaviny82/fix-combobox-right-alignment
Browse files Browse the repository at this point in the history
[Settings] Fix flyout position when ComboBox is aligned to the right
  • Loading branch information
natsurainko authored Feb 19, 2023
2 parents 6b41d28 + 676e250 commit 118d8e0
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Automation.Provider;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.Xaml.Interactivity;
using Windows.Foundation.Collections;

namespace Natsurainko.FluentLauncher.Behaviors
{
class SetComboBoxWidthFromItemsBehavior : Behavior<ComboBox>
{
public static readonly DependencyProperty SetComboBoxWidthFromItemsProperty =
DependencyProperty.RegisterAttached
(
"SetComboBoxWidthFromItems",
typeof(bool),
typeof(SetComboBoxWidthFromItemsBehavior),
new PropertyMetadata(false, OnSetComboBoxWidthFromItemsPropertyChanged)
);

public bool SetComboBoxWidthFromItems
{
get => (bool)GetValue(SetComboBoxWidthFromItemsProperty);
set => SetValue(SetComboBoxWidthFromItemsProperty, value);
}

protected override void OnAttached()
{
AssociatedObject.Loaded += OnComboBoxLoaded;
AssociatedObject.Items.VectorChanged += Items_VectorChanged;
}

public void Items_VectorChanged(IObservableVector<object> sender, IVectorChangedEventArgs e)
{
SetComboBoxWidth(AssociatedObject);
}

private static void OnComboBoxLoaded(object sender, RoutedEventArgs e)
{
SetComboBoxWidth((ComboBox)sender);
}

private static void OnSetComboBoxWidthFromItemsPropertyChanged(
DependencyObject dpo,
DependencyPropertyChangedEventArgs e)
{
SetComboBoxWidthFromItemsBehavior behavior = (SetComboBoxWidthFromItemsBehavior)dpo;
ComboBox comboBox = behavior.AssociatedObject;

bool newValue = (bool)e.NewValue;
bool oldValue = (bool)e.OldValue;

if (comboBox != null && newValue != oldValue)
{
if (newValue == true)
{
comboBox.Loaded += OnComboBoxLoaded;
comboBox.Items.VectorChanged += behavior.Items_VectorChanged;

}
else
{
comboBox.Loaded -= OnComboBoxLoaded;
comboBox.Items.VectorChanged -= behavior.Items_VectorChanged;
}
}
}

/// <summary>
/// Set the width of a ComboBox to the longest item in its drop down menu
/// </summary>
/// <param name="comboBox">Target</param>
private static void SetComboBoxWidth(ComboBox comboBox)
{
// Open ComboBox drop down and prepare ItemContainerGenerator
comboBox.IsDropDownOpen = true;
comboBox.ItemContainerGenerator.StartAt(new GeneratorPosition(0, 0), GeneratorDirection.Forward, true);

double maxWidth = 0;
ComboBoxItem? item;
while ((item = comboBox.ItemContainerGenerator.GenerateNext(out _) as ComboBoxItem) != null)
{
item.Measure(new Windows.Foundation.Size(double.PositiveInfinity, double.PositiveInfinity));
var size = item.DesiredSize;
if (size.Width > maxWidth)
{
maxWidth = size.Width;
}
}

maxWidth += 20; // This constant adds more space to include the drop down button and paddings
comboBox.Width = maxWidth > 70 ? maxWidth : 70; // Ensures a MinWidth of 70 when there is no content; Less width will result in issues with appearance
comboBox.ItemContainerGenerator.Stop();
comboBox.IsDropDownOpen = false;
}
}
}
11 changes: 8 additions & 3 deletions Natsurainko.FluentLauncher/Views/Pages/Settings/Launch.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
xmlns:local="using:Natsurainko.FluentLauncher.Views.Pages.Settings"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:Natsurainko.FluentLauncher.ViewModels.Pages.Settings"
xmlns:behaviors ="using:Natsurainko.FluentLauncher.Behaviors"
Background="Transparent"
xmlns:i="using:Microsoft.Xaml.Interactivity"
mc:Ignorable="d">
<Page.DataContext>
<vm:Launch />
Expand Down Expand Up @@ -41,19 +43,23 @@
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="15" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" x:Name="container1"/>
</Grid.ColumnDefinitions>
<TextBlock
x:Uid="Settings_Launch_Item_1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="Current .minecraft folder:" />
<ComboBox
Grid.Column="2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FlowDirection="RightToLeft"
ItemsSource="{Binding GameFolders}"
MaxWidth="{Binding ElementName=container1, Path=ActualWidth, Mode=OneTime}"
SelectedItem="{Binding CurrentGameFolder, Mode=TwoWay}">
<i:Interaction.Behaviors>
<behaviors:SetComboBoxWidthFromItemsBehavior SetComboBoxWidthFromItems="True"/>
</i:Interaction.Behaviors>
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="x:String">
<TextBlock Text="{Binding}" TextTrimming="CharacterEllipsis" />
Expand Down Expand Up @@ -151,7 +157,6 @@
Grid.Column="2"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FlowDirection="RightToLeft"
ItemsSource="{Binding JavaRuntimes}"
SelectedItem="{Binding CurrentJavaRuntime, Mode=TwoWay}">
<ComboBox.ItemTemplate>
Expand Down

0 comments on commit 118d8e0

Please sign in to comment.