Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bound commands not getting fired for partially visible items inside a listbox

Tags:

c#

wpf

xaml

listbox

In my XAML I've got a ListBox which is bound to a list of viewmodel objects.

A usercontrol is defined to use this TestViewModel as its data context. In the usercontrol I've got 2 command buttons which are bound to methods using ICommand pattern. With the help these buttons I'm able to add and remove viewmodels to the above mentioned list, which makes the ListBox to grow in height (which makes the scrollbars to appear).

Everything seems to be working fine. However, things don't work as the expected way, when the usercontrols are partially shown because of the screen/application height is not enough.

Even though commands buttons are visible, the commands are not getting fired. Instead, The ListBox is getting scrolled to the last item and the partially shown item becomes fully visible. After that the commands for that item is getting fired as expected.

Setting a fixed height for the ListBox is not an option, as the application has to support different screen resolutions.

Anybody has any idea how to fix this? Or is this an expected behavior?

Update: Adding the sample source codes. My current screen resolution is 1366x768. Under that I'm able to see only 2 full controls. 3rd one is visible only partially.

Window:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:uc="clr-namespace:WpfApplication1"
        Title="MainWindow" WindowState="Maximized">
    <Window.DataContext>
        <uc:MainViewModel></uc:MainViewModel>
    </Window.DataContext>
    <Grid>
        <ListBox ItemsSource="{Binding VmList}"></ListBox>
    </Grid>
</Window>

Viewmodel for window:

public class MainViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }


        private ObservableCollection<TestViewModel> vmList;

        public ObservableCollection<TestViewModel> VmList
        {
            get { return vmList; }
            set 
            { 
                vmList = value;
                OnPropertyChanged("VmList");
            }
        }

        public MainViewModel()
        {
            VmList = new ObservableCollection<TestViewModel>() 
            {
                new TestViewModel(1),
                new TestViewModel(2),
                new TestViewModel(3)
            };
        }    
    }

Usercontrol:

<UserControl x:Class="WpfApplication1.TestUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" Height="300" Width="200">    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>  
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="85*"></ColumnDefinition>
            <ColumnDefinition Width="15*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Border BorderThickness="1" BorderBrush="Gray" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2">
        <Grid Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center">
                <Border BorderThickness="2" BorderBrush="Black">
                    <Label Content="{Binding Count}"></Label></Border>
        </Grid></Border>
        <Button Grid.Row="0" Grid.Column="1" Width="30" Height="30" Command="{Binding OnControlAdd}"
                CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext}">+</Button>
    </Grid>
</UserControl>

Viewmodel for usercontrol:

public class TestViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private int count;

        public int Count
        {
            get { return count; }
            set { count = value; }
        }


        public ICommand OnControlAdd
        {
            get
            {
                return new RelayCommand(AddControl);
            }
        }

        private void AddControl(object param)
        {
            MainViewModel mainView = param as MainViewModel;

            if (null != mainView)
            {
                mainView.VmList.Add(new TestViewModel(mainView.VmList.Count + 1));
            }
        }

        public TestViewModel(int count)
        {
            Count = count;
        }
    }

Datatemplate:

<DataTemplate DataType="{x:Type local:TestViewModel}">        
        <local:TestUserControl></local:TestUserControl>
    </DataTemplate>
like image 993
Thusitha Avatar asked Dec 11 '25 12:12

Thusitha


1 Answers

Yes, this is expected behavior, firstly ListBox's ScrollViewer will ensure what item content is fully visible when you click item (it will eat click, so it won't reach button) and only then you can click button inside item.

To fix it, simply disable that behavior with

    <ListBox ScrollViewer.CanContentScroll="False" ... />
like image 167
Sinatr Avatar answered Dec 14 '25 01:12

Sinatr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!