Search code examples
c#winui-3

WinUI 3 - ComboBox not work properly in Flyout


I've a listview. Its listviewitems contain a textblock and two fonticon. A fonticon has an AttachedFlyout with combobox loaded with objects when I open the window. I set the selecteditem of every combobox to first element of the list.

When I open/close the flyout in a comboboxitem and reopen the same flyout, it work fine, but if I open the flyout in other comboboxitem, the previous combobox selecteditem is resetted to -1 index.

enter image description here

This is the ItemTemplate:

        <DataTemplate x:Key="ItemDataTemplate"
                  x:DataType="vm:ReflectionType">
        <UserControl>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="auto" />
                    <ColumnDefinition Width="auto" />
                </Grid.ColumnDefinitions>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup>
                        <VisualState x:Name="ascendente">
                            <VisualState.StateTriggers>
                                <triggers:CompareStateTrigger Comparison="Equal"
                                                              Value="{x:Bind Sorting,Mode=TwoWay}"
                                                              To="Ascendente" />
                            </VisualState.StateTriggers>
                            <VisualState.Setters>
                                <Setter Target="sort.Glyph"
                                        Value="&#xE74A;" />
                                <Setter Target="sort.(ToolTipService.ToolTip)"
                                        Value="Ascendente" />
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="discendente">
                            <VisualState.StateTriggers>
                                <triggers:CompareStateTrigger Comparison="Equal"
                                                              Value="{x:Bind Sorting,Mode=TwoWay}"
                                                              To="Discendente" />
                            </VisualState.StateTriggers>
                            <VisualState.Setters>
                                <Setter Target="sort.Glyph"
                                        Value="&#xE74B;" />
                                <Setter Target="sort.(ToolTipService.ToolTip)"
                                        Value="Discendente" />

                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="nonordinato">
                            <VisualState.StateTriggers>
                                <triggers:CompareStateTrigger Comparison="Equal"
                                                              Value="{x:Bind Sorting,Mode=TwoWay}"
                                                              To="NonOrdinato" />
                            </VisualState.StateTriggers>
                            <VisualState.Setters>
                                <Setter Target="sort.Glyph"
                                        Value="&#xE8CB;" />
                                <Setter Target="sort.(ToolTipService.ToolTip)"
                                        Value="Non ordinato" />

                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
                <TextBlock Text="{x:Bind DisplayProprieta,Mode=OneWay}" />
                <FontIcon FontFamily="Segoe MDL2 Assets"
                          x:Name="sort"
                          Grid.Column="1"
                          ToolTipService.ToolTip="Ordina"
                          FontSize="12"
                          Margin="10,0,0,0"
                          ap:CommandAttachedProperty.ElementCommand="{x:Bind SetSortingCommand}"
                          Glyph="&#xE8CB;" />
                <FontIcon FontFamily="Segoe MDL2 Assets"
                          FontSize="12"
                          Margin="10,0,0,0"
                          ToolTipService.ToolTip="Filtro"
                          FlyoutBase.AttachedFlyout="{StaticResource fo}"
                          ap:CommandAttachedProperty.ElementCommand="{x:Bind OpenCloseFilterCommand}"
                          ap:FlyOutOpenCloseAttachedPropery.IsOpen="{x:Bind IsFilter,Mode=OneWay}"
                          Grid.Column="2"
                          Glyph="&#xE71C;" />



            </Grid>
            
        </UserControl>
    </DataTemplate>

This is the Attached Flyout:

        <Flyout x:Key="fo">
        <Flyout.FlyoutPresenterStyle>
            <Style TargetType="FlyoutPresenter">
                <Setter Property="ScrollViewer.HorizontalScrollMode"
                        Value="Disabled" />
                <Setter Property="ScrollViewer.HorizontalScrollBarVisibility"
                        Value="Disabled" />
                <Setter Property="IsTabStop"
                        Value="True" />
                <Setter Property="AllowFocusOnInteraction"
                        Value="True" />
            </Style>
        </Flyout.FlyoutPresenterStyle>
        <StackPanel Spacing="3">
            <CommandBar DefaultLabelPosition="Right"
                        Padding="0"
                        HorizontalAlignment="Left">
                <AppBarButton Icon="Clear"
                              Label="Reset" 
                              Command="{Binding ResetCommand}"/>
            </CommandBar>
            <ComboBox ItemsSource="{Binding ListaConfronti}"
                      DisplayMemberPath="CompareText"
                      HorizontalAlignment="Stretch"
                      SelectedItem="{Binding SelectedCompare,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
            <ContentControl ContentTemplateSelector="{StaticResource Selector}"
                            HorizontalContentAlignment="Stretch"
                            Content="{Binding Valori,Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>

    </Flyout>

This is the viewmodel:

    public partial class FilterManagerForList:ObservableObject
{
    [ObservableProperty] ObservableCollection<ReflectionType> _items=new();
    [ObservableProperty] Type _tipoOggetto;

    public void Manager(Type objType)
    {
        if(TipoOggetto is not null)
        {
            foreach (var item2 in objType.GetProperties())
            {
                ReflectionType rt = new();
                rt.NomeProprieta = item2.Name;
                rt.DisplayProprieta = item2.CustomAttributes.Any() ? item2.CustomAttributes.First().NamedArguments.First().TypedValue.ToString() : item2.Name;
                rt.DisplayProprieta=rt.DisplayProprieta.Trim('\"');
                rt.TipoProprieta = item2.PropertyType;
                Items.Add(rt);
            }
        }
    }

    [RelayCommand]
    void ApplicaFiltro()
    {
        var lista=Items.Where(c => c.Valori is ValueChild && c.Valori.Value is not null);
        List<dynamic> lst = new List<dynamic>();

        foreach (var item in lista)
        {
            var tipoConfronto = item.SelectedCompare.MongoCompare;
            if (item.SelectedCompare.Tipo == TipiProprieta.Stringa)
            {
                if (tipoConfronto == "$eq")
                {
                    var match = GetObj();
                    var confronto=GetObj();
                    confronto.Add(item.NomeProprieta,item.Valori.Value);
                    match.Add("$match", confronto);
                    lst.Add(match);
                }
            }

        }

        var tt=JsonSerializer.Serialize(lst);
    }

    partial void OnTipoOggettoChanged(Type oldValue, Type newValue)
    {
        if(newValue is not null)
            Manager(newValue);
    }

    IDictionary<string,object> GetObj()
    {
        dynamic dynamicObj = new ExpandoObject();
        return (IDictionary<string, object>)dynamicObj;
    }

}

This is ReflectionType model:

    public partial class ReflectionType : ObservableObject
{

    [ObservableProperty] string _nomeProprieta;
    [ObservableProperty] string _displayProprieta;
    [ObservableProperty] Type _tipoProprieta;
    [ObservableProperty] ValueChild _valori;

    [ObservableProperty] SortOrder _sorting;
    [ObservableProperty] bool _isFilter;

    public List<CompareItem> ListaConfronti { get; set; }
    [ObservableProperty] CompareItem _selectedCompare;

    [RelayCommand]
    void Reset()
    {
        //Valori = new();
        //var item = ListaConfronti[0];
        //SelectedCompare = new(item.CompareText, item.CompareVersion, item.Tipo);

        //SelectedCompare = null;
        SelectedCompare = ListaConfronti[0];

        //Valori.Reset = true;
        //Valori.Reset=false;
    }

    [RelayCommand]
    void SetSorting()
    {
        if(Sorting==SortOrder.NonOrdinato) Sorting=SortOrder.Ascendente;
        else if(Sorting==SortOrder.Ascendente) Sorting=SortOrder.Discendente;
        else Sorting=SortOrder.NonOrdinato;
    }

    [RelayCommand]
    void OpenCloseFilter()
    {
        IsFilter = !IsFilter;
    }

    partial void OnTipoProprietaChanged(Type oldValue, Type newValue)
    {
        if (newValue == typeof(int) ||
            newValue == typeof(uint) ||
            newValue == typeof(decimal) ||
            newValue == typeof(long) ||
            newValue == typeof(ulong) ||
            newValue == typeof(double) ||
            newValue == typeof(byte))
        {
            ListaConfronti = new()
            {
                new(){CompareText = "Uguale a",CompareVersion = 1,Tipo=TipiProprieta.Numero,MongoCompare="$eq" },
                new(){CompareText = "Maggiore uguale a",CompareVersion = 1,Tipo=TipiProprieta.Numero,MongoCompare="$gte" },
                new(){CompareText = "Maggiore di",CompareVersion = 1,Tipo=TipiProprieta.Numero,MongoCompare="$gt" },
                new(){CompareText = "Minore uguale a",CompareVersion = 1,Tipo=TipiProprieta.Numero,MongoCompare="$lte" },
                new(){CompareText = "Minore di",CompareVersion = 1,Tipo=TipiProprieta.Numero,MongoCompare="$lt"},
                new(){CompareText = "Compreso tra",CompareVersion = 2,Tipo=TipiProprieta.Numero,MongoCompare="$in"},
                new(){CompareText = "Diverso da",CompareVersion = 1,Tipo=TipiProprieta.Numero,MongoCompare="$ne"}
            };
        }
        else if (newValue == typeof(string))
        {
            ListaConfronti = new()
            {
                new(){CompareText = "Uguale a",CompareVersion = 1,Tipo=TipiProprieta.Stringa,MongoCompare="$eq" },
                new(){CompareText = "Diverso da",CompareVersion = 1,Tipo=TipiProprieta.Stringa,MongoCompare="$ne" },
                new(){CompareText = "Contiene",CompareVersion = 1,Tipo=TipiProprieta.Stringa,MongoCompare="$in"},
                new(){CompareText = "Inizia con",CompareVersion = 1,Tipo=TipiProprieta.Stringa,MongoCompare="$start"},
                new(){CompareText = "Finisce con",CompareVersion = 1,Tipo=TipiProprieta.Stringa,MongoCompare="$end"}
            };
        }
        else if (newValue == typeof(bool))
        {
            ListaConfronti = new()
            {
                new(){CompareText = "Uguale a",CompareVersion=1,Tipo=TipiProprieta.Booleano,MongoCompare="$eq"}
            };

        }
        else if (newValue == typeof(DateTime))
        {
            ListaConfronti = new()
            {
                new(){CompareText = "Uguale a",CompareVersion = 1,Tipo=TipiProprieta.Data,MongoCompare="$eq" },
                new(){CompareText = "Maggiore uguale",CompareVersion = 1,Tipo=TipiProprieta.Data,MongoCompare="$eq" },
                new(){CompareText = "Maggiore di",CompareVersion = 1,Tipo=TipiProprieta.Data,MongoCompare="$gt" },
                new(){CompareText = "Minore uguale",CompareVersion = 1,Tipo=TipiProprieta.Data,MongoCompare="$eq" },
                new(){CompareText = "Minore di",CompareVersion = 1,Tipo=TipiProprieta.Data,MongoCompare="$lt"},
                new(){CompareText = "Compreso tra",CompareVersion = 2,Tipo=TipiProprieta.Data,MongoCompare="$in"},
                new(){CompareText = "Diverso da",CompareVersion = 1,Tipo=TipiProprieta.Data,MongoCompare="$ne"}
            };

        }


        if (oldValue is null && SelectedCompare is null)
            SelectedCompare = ListaConfronti[0];
    }

    partial void OnSelectedCompareChanged(CompareItem oldValue, CompareItem newValue)
    {
        if (newValue is null) return;
        if (newValue.CompareVersion == 1)
        {
            //if(Valori is null)
                Valori = new(newValue);
            //Valori.DefinizioneProprieta = newValue;

        }
        else if (newValue.CompareVersion == 2)
        {
            //if (Valori is null)
                Valori = new ValueChildBetween(newValue);
            Valori.DefinizioneProprieta = newValue;
        }

    }




}

Thanks


Solution

  • I noted that if I use the flyout in page resources it not working properly, while if I use the same flyout in fonticon, it work fine.

    Not working:

    <Page.Resource>
               <Flyout x:Key="fo">
            <Flyout.FlyoutPresenterStyle>
                <Style TargetType="FlyoutPresenter">
                    <Setter Property="ScrollViewer.HorizontalScrollMode"
                            Value="Disabled" />
                    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility"
                            Value="Disabled" />
                    <Setter Property="IsTabStop"
                            Value="True" />
                    <Setter Property="AllowFocusOnInteraction"
                            Value="True" />
                </Style>
            </Flyout.FlyoutPresenterStyle>
            <StackPanel Spacing="3">
                <CommandBar DefaultLabelPosition="Right"
                            Padding="0"
                            HorizontalAlignment="Left">
                    <AppBarButton Icon="Clear"
                                  Label="Reset" 
                                  Command="{Binding ResetCommand}"/>
                </CommandBar>
                <ComboBox ItemsSource="{Binding ListaConfronti}"
                          DisplayMemberPath="CompareText"
                          HorizontalAlignment="Stretch"
                          SelectedItem="{Binding SelectedCompare,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                <ContentControl ContentTemplateSelector="{StaticResource Selector}"
                                HorizontalContentAlignment="Stretch"
                                Content="{Binding Valori,Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
            </StackPanel>
    
        </Flyout>
    </Page.Resources>
                        <FontIcon FontFamily="Segoe MDL2 Assets"
                              x:Name="fiFiltro"
                              FontSize="12"
                              Margin="10,0,0,0"
                              FlyOutBase.AttachedAttachedFlyOut="{StaticResource fo}"
                              ToolTipService.ToolTip="Filtro"
                              ap:CommandAttachedProperty.ElementCommand="{x:Bind OpenCloseFilterCommand}"
                              ap:CommandAttachedProperty.ElementCommandParameter="{Binding ElementName=fiFiltro}"
                              Grid.Column="2"
                              Glyph="&#xE71C;"/>
    

    It working:

                        <FontIcon FontFamily="Segoe MDL2 Assets"
                              x:Name="fiFiltro"
                              FontSize="12"
                              Margin="10,0,0,0"
                              ToolTipService.ToolTip="Filtro"
                              ap:CommandAttachedProperty.ElementCommand="{x:Bind OpenCloseFilterCommand}"
                              ap:CommandAttachedProperty.ElementCommandParameter="{Binding ElementName=fiFiltro}"
                              Grid.Column="2"
                              Glyph="&#xE71C;">
                        <FlyoutBase.AttachedFlyout>
                            <Flyout>
                                <Flyout.FlyoutPresenterStyle>
                                    <Style TargetType="FlyoutPresenter">
                                        <Setter Property="ScrollViewer.HorizontalScrollMode"
                                                Value="Disabled" />
                                        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility"
                                                Value="Disabled" />
                                        <Setter Property="IsTabStop"
                                                Value="True" />
                                        <Setter Property="AllowFocusOnInteraction"
                                                Value="True" />
                                    </Style>
                                </Flyout.FlyoutPresenterStyle>
                                <StackPanel Spacing="3">
                                    <CommandBar DefaultLabelPosition="Right"
                                                Padding="0"
                                                HorizontalAlignment="Left">
                                        <AppBarButton Icon="Clear"
                                                      Label="Reset"
                                                      Command="{Binding ResetCommand}" />
                                    </CommandBar>
                                    <ComboBox ItemsSource="{Binding ListaConfronti}"
                                              DisplayMemberPath="CompareText"
                                              HorizontalAlignment="Stretch"
                                              SelectedItem="{Binding SelectedCompare,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                                    <ContentControl ContentTemplateSelector="{StaticResource Selector}"
                                                    HorizontalContentAlignment="Stretch"
                                                    Content="{Binding Valori,Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
                                </StackPanel>
    
                            </Flyout>
    
                        </FlyoutBase.AttachedFlyout>
                    </FontIcon>
    

    Thanks to you.