none
Silverlight 4 ListBox (ListBoxItems) hide Problem

    Question

  • Hi,

    I have Silverlight 4 Application developed with the MVVM Pattern. I have also a
    PagedCollectionView bind on my Controls. The Items are Tasks that should be filtered
    in 4 categories (fill 4 different ListBoxes) impotent is that the filter is
    static. I have also another dynamic Filter for the user, that provides
    filtering by dates (day, week, month..).

    So for the categories filter I use a Converter that set the visibilities of the
    ListboxItems to collapsed.

    For the dynamic filter I user the PagedCollectionView filter possibilities.

    The works also as expected, but there are empty spaces for the hiding Listboxitems and when
    the user goes with the Mouse over the empty space, he can mark the item. So the
    Items are not really hidden.

    I use a WrapPanel for the Items.

    So I know that cotrols are binding directly to the collection, but when I set the visibility
    to collapse  I expect that the items
    should hide.

    Converter:

     public object Convert(object value, Type targetType, object parameter,

                 System.Globalization.CultureInfo culture)

            {

                if (value != null)

                {

                    string prio = parameter as String;

                    var v = value.ToString();

                    if (prio != v) return Visibility.Collapsed;

                }

                return Visibility.Visible;

            }

     

    Xaml:  <Style TargetType="ListBox" >
                <Setter Property="ItemsPanel">
                    <Setter.Value>
                        <ItemsPanelTemplate>
                         <controlsToolkit:WrapPanel />
                        </ItemsPanelTemplate>
                    </Setter.Value>
                </Setter>
                <Setter 
            Property="ScrollViewer.HorizontalScrollBarVisibility" 
            Value="Disabled" 
            />

     

     <ListBox Name="ListBoxA" ItemsSource="{Binding Tasks}" Margin="0,15,0,0" Background="{StaticResource Background-Brush}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <Grid Width="80" Margin="1" Visibility="{Binding Path=Prio, ConverterParameter='A' ,Converter={StaticResource TaskFilter}}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="2" />
                                    <ColumnDefinition />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto" />
                                </Grid.RowDefinitions>
                                <Rectangle  RadiusX="0" RadiusY="0" Grid.RowSpan="5" Grid.ColumnSpan="2" UseLayoutRounding="True">
                                    <Rectangle.Fill>
                                        <LinearGradientBrush StartPoint="0,0" EndPoint="0,0">
                                            <!--<GradientStop Color="White" Offset="0" />-->
                                            <GradientStop Color="#FFEEFB08" Offset="4" />
                                        </LinearGradientBrush>
                                    </Rectangle.Fill>
                                </Rectangle>
                                <TextBlock Name="NameField" Text="{Binding Path=Taskname}" Margin="4,2,2,2" Grid.Row="0" Grid.Column="1" FontWeight="Bold" FontSize="12" IsHitTestVisible="False" />
                               
                            </Grid>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

     

    I also tried to define the ListBoxItems but it doesn’t work.

    I would be grateful for any help.

    Thanks.

    Martin

    Friday, January 27, 2012 4:07 AM

All replies

  • Allright,

     

    Have you tried to also change the IsEnabled property of the ListboxItem?

     

    http://tozon.info/blog/post/2009/03/10/Disabling-items-in-a-Silverlight-ListBox.aspx

     

     

    Friday, January 27, 2012 7:52 AM
  • Hi,

    Thank you for your replay. I tried but still not working:

      <ListBox.ItemTemplate>
                          
                        <DataTemplate>
                            <ListBoxItem IsEnabled="{Binding Path=Prio, Converter={StaticResource ConvertIsEnablad}}">
                            <Grid Width="80"  Margin="1" Visibility="{Binding Path=Prio, ConverterParameter='B' ,Converter={StaticResource TaskFilter}}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="2" />
                                    <ColumnDefinition />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto" />
                                    <!--<RowDefinition Height="Auto" />-->
                                </Grid.RowDefinitions>
                                <Rectangle  RadiusX="0" RadiusY="0" Grid.RowSpan="5" Grid.ColumnSpan="2" UseLayoutRounding="True">
                                    <Rectangle.Fill>
                                        <LinearGradientBrush StartPoint="0,0" EndPoint="0,0">
                                            <!--<GradientStop Color="White" Offset="0" />-->
                                            <GradientStop Color="#FFF8F83D" Offset="4" />
                                        </LinearGradientBrush>
                                    </Rectangle.Fill>
                                    <!--<Rectangle.Effect>
                                        <DropShadowEffect ShadowDepth="2" />
                                    </Rectangle.Effect>-->
                                </Rectangle>
                                <TextBlock Name="NameField" Text="{Binding Path=Taskname}" Margin="4,2,2,2" Grid.Row="0" Grid.Column="1" FontWeight="Bold" FontSize="12" IsHitTestVisible="False" />
                                <!--<TextBlock Name="NameField" Text="{Binding Path=Taskname}" Margin="4,2,2,2" Grid.Row="0" Grid.Column="1" FontWeight="Bold" FontSize="12" />-->
                                <!--StackPanel Orientation="Horizontal" Grid.Row="3" Grid.Column="1">
                                    <TextBlock Text="{Binding Path=DueDate, StringFormat=dd.MM.yyyy}" Margin="4,0,0,2" />
                                </StackPanel>-->
                            </Grid>
                            </ListBoxItem>
                        </DataTemplate>
     
     
                    </ListBox.ItemTemplate>
     
    The "invisible"-Items in the Listbox are still there
    Friday, January 27, 2012 8:54 AM
  • Hi makasov,

    As far as I know ,you cannot do it ,for the silverlight listbox will foreach all items in the datasource.

    So remove the item in the datasource and save it in another list may be the solution.

    Wednesday, February 01, 2012 12:24 AM
  • Hi Anna,

    Thank you for your reply, but as I wrote in my first post I know this.

    But why is there the possibility for hiding controlls with converters when this dont work.

    In my case I need 4 additional collection for my categories, that's ugly.

     

    Wednesday, February 01, 2012 6:47 AM
  • Another way is to do filtering yourself in the ViewModel, I have used this in the past to create various UI elements that allow the user to Filter data present in the ViewModel. I'm not using a PageViewCollection but an extra collection that contains only filtered items.

     

    Hope this helps!

     

     public partial class MainPage : UserControl
        {
            public class Model
            {
                public string Name { get; set; }
                public string Title { get; set; }
                public string Type { get; set; }
    
                public override string ToString()
                {
                    return string.Concat(Name, Title, Type);
                }
            }
    
            public class ModelFilter<T>
                where T : Model
            {
                public string Description { get; set; }
                public Func<T, bool> Predicate { get; set; }
    
                public ModelFilter(string description, Func<T, bool> predicate)
                {
                    this.Description = description;
                    this.Predicate = predicate;
                }
    
                public override string ToString()
                {
                    return this.Description;
                }
            }
    
            public class VM
            {
                /// <summary>
                ///  Private list contains unfiltered data
                /// </summary>
                private List<Model> unfilteredData;
    
                /// <summary>
                /// ObservableCollection that contains filtered data
                /// </summary>
                public ObservableCollection<Model> FilteredData
                {
                    get
                    {
                        return this.filteredData;
                    }
                    set
                    {
                        this.filteredData = value;
    
                    }
                }
                public ObservableCollection<Model> filteredData;
    
                /// <summary>
                /// The currently selected Filter (databound to combobox)
                /// </summary>
                public ModelFilter<Model> SelectedFilter
                {
                    get
                    {
                        return this.selectedFilter;
                    }
                    set
                    {
                        this.selectedFilter = value;
                        this.FilterData();
                    }
                }
                private ModelFilter<Model> selectedFilter;
    
                /// <summary>
                /// The list of possible Filters (databound to combobox)
                /// </summary>
                public ObservableCollection<ModelFilter<Model>> Filters
                {
                    get
                    {
                        return this.filters;
                    }
                    set
                    {
                        this.filters = value;
                    }
                }
                private ObservableCollection<ModelFilter<Model>> filters;
    
                public VM()
                {
                    // Create lists
                    this.filteredData = new ObservableCollection<Model>();
                    this.unfilteredData = new List<Model>();
    
                    // Populate filters
                    this.Filters = new ObservableCollection<ModelFilter<Model>>()
                    {
                        // returns all unfiltereditems
                        new ModelFilter<Model>("All", m => true),
    
                        // returns unfiltereditems that have type equal to "FTE"
                        new ModelFilter<Model>("FTEs", m => m.Type.Equals("FTE")),
    
                        // returns unfiltereditems that have tile equal to "Engineers"
                        new ModelFilter<Model>("Engineers", m => m.Title.Equals("Engineer")),
                    };
    
                    // Chose first filter (all)
                    this.SelectedFilter = this.Filters.FirstOrDefault();
                }
    
                /// <summary>
                /// Loads the data
                /// </summary>
                public void LoadData()
                {
                    // Load data
                    this.unfilteredData = new List<Model>()
                    {
                        new Model() {
                             Name = "Model 1",
                             Title = "Engineer",
                             Type = "FTE",
                        },
                        new Model() {
                             Name = "Model 2",
                             Title = "Engineer",
                             Type = "FTE",
                        },
                        new Model() {
                             Name = "Model 3",
                             Title = "Manager",
                             Type = "Contractor",
                        },
                    };
    
                    // Filter data (this can be called from LoadAsyncCompleted)
                    this.FilterData();
                }
    
                /// <summary>
                /// Filters the data
                /// </summary>
                void FilterData()
                {
                    // Check for data
                    if (this.unfilteredData == null)
                        return;
    
                    // Start with all data
                    var items = this.unfilteredData;
    
                    // Check if current filter present
                    // Then filter using the ModelFilter lambda
                    if (this.SelectedFilter != null)
                        items = items.Where(this.SelectedFilter.Predicate).ToList();
    
                    
                    // Clear the FilteredData
                    this.FilteredData.Clear();
    
                    // Add filtered items
                    foreach (var item in items)
                        this.FilteredData.Add(item);
                }
            }
    
            public MainPage()
            {
                InitializeComponent();
    
                // Create VM and load
                var vm = new VM();
                vm.LoadData();
    
                // DataConetxt for binding
                this.DataContext = vm;
            }
        }

    And here is the XAML: 

        <Grid x:Name="LayoutRoot" Background="White">
            <StackPanel>
                <ComboBox ItemsSource="{Binding Filters}" SelectedItem="{Binding SelectedFilter, Mode=TwoWay}" />
                <ListBox ItemsSource="{Binding FilteredData}" />
            </StackPanel>
        </Grid>
    Wednesday, February 01, 2012 11:21 AM
  • Hi,

     

    Thank you for your example. I use also Paging, Sorting and the most important thing is the built in CurrentItem functionallity.

    How would you implement the CurrentItem property. So if i have 4 Listboxes with 4 filtered collection and I select an item in listbox A  the same item is selected in a Grid - and in the other direction. Without playing arround with the selectedItem property of the listbox.

    So in every collection i have na selecteditem property.

    Somethink like that doesnt work correctlly, becouse there are diferent collections:

    public TaskViewModel SelectedTask
            {
                get { return _selectedTask; }
                set
                {
                    _selectedTask = value;
                    NotifyPropertyChanged("SelectedTask");
                }
            } 

     

    If i leave the first listbox and go to the next, than the first selecteditem remains selected and when I go back and click exactlly the same item nothing hapens because it is in this collection allredy selected.

    Thanks

    Best Regards

     

     

    Friday, February 03, 2012 2:27 AM
  • If I'm understanding correctly you have a page that contains 4 Listbox's. When you select an item in one of them you want to show the selected item preview elsewhere.

    I would create a SelectedItem property on the ViewModel for that and databind it to the SelectedItem property of the Listbox. When dealing with multiple Listbox's I would simply create more SelectedItems in the ViewModel.

    The SelectedItem property of the Listbox control is only updated when the selection is changed. If you want something to happen when you focus the Listbox without changing the selection you can perhaps use the GotFocus, Click or MouseLeftButtonUp events.

    To only show the SelectedItem of the currently focussed Listbox and the collection that it binds to, you can use the TabControl. Add the previews for the SelectedItems to the tab control as tabs. Then databind the SelectedIndex property of the TabControl to a SelectedListboxIndex in the ViewModel and update that as you change SelectedItems for the Listbox's.

    Hope that makes sense.

    Sunday, February 05, 2012 6:17 PM