none
Binding Visibility of StackPanel in a ListBox.ItemTemplate

    Question

  • Hi,

    I'm trying to setup an item template which has a couple of nested StackPanels in it.  I'm trying to set the visibility of one of the panels to the IsSelected proprety of the ListBoxItem.  I've tried this with no luck:

            <ListBox Name="listBox1" Margin="0,0,0,0" SelectionChanged="listBox1_SelectionChanged">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Vertical">
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="This is where the person's info goes, picture, name, and stuff, the color of the row changes based on his status, and stuff like that" TextWrapping="Wrap" Height="100" Width="600"/>
                            </StackPanel>
                            <StackPanel Orientation="Horizontal" x:Name="buttonsPanel" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}" >
                                <RadioButton x:Name="presentButton"  Content="Present" Width="100" ClickMode="Press" IsTabStop="False"/>
                                <RadioButton x:Name="absentButton" Content="Absent" Width="100" ClickMode="Press" IsTabStop="False"/>
                                <RadioButton x:Name="excusedButton" Content="Excused" Width="100" ClickMode="Press" IsTabStop="False"/>
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
    

     The point is that the last StackPanel should only be displayed for the selected item.

    Does anyone know what I'm doing wrong here?

    Thanks

     

    Tuesday, September 20, 2011 5:37 PM

Answers

  • Hi Ali,

    Below is my test code, and the StackPanel only be displayed for the selected item. You may have a try.

    .xaml

    <UserControl x:Class="BindingVisibility.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:myproject="clr-namespace:BindingVisibility" 
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">
    
        <UserControl.Resources>
            <myproject:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />     
        </UserControl.Resources>
        <Grid x:Name="LayoutRoot" Background="White">
           
            <ListBox Name="listBox1" Margin="0,0,0,0" >
                <ListBox.ItemContainerStyle>
                    <Style TargetType="ListBoxItem">
                        <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}" >
                        </Setter>
                    </Style>
                </ListBox.ItemContainerStyle>
    
                    <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Vertical"   >
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="This is where the person's info goes, picture, name, and stuff, the color of the row changes based on his status, and stuff like that" TextWrapping="Wrap" Height="100" Width="600"/>
                            </StackPanel>
                            <TextBlock Text="{Binding Name}" />
                            
                            <StackPanel Orientation="Horizontal" x:Name="buttonsPanel" Visibility="{Binding Path=IsSelected,Converter={StaticResource BooleanToVisibilityConverter},Mode=TwoWay}"   >
                                <RadioButton x:Name="presentButton"  Content="Present" Width="100" ClickMode="Press" IsTabStop="False"/>
                                <RadioButton x:Name="absentButton" Content="Absent" Width="100" ClickMode="Press" IsTabStop="False"/>
                                <RadioButton x:Name="excusedButton" Content="Excused" Width="100" ClickMode="Press" IsTabStop="False"/>
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </UserControl>

    .cs

    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Collections.ObjectModel;
    using System.Windows.Data;
    using System.ComponentModel;
    
    namespace BindingVisibility
    {
        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();         
                listBox1.ItemsSource = GridData.GetData();
            }          
        }
    
        public class GridData : INotifyPropertyChanged
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public bool Male { get; set; }
            private bool isSelected;
    
            public bool IsSelected
            {
                get 
                { 
                    return isSelected;
                }
                set 
                { 
                    isSelected = value;
                    NotifyPropertyChanged("IsSelected");
                }
            }
    
            public static ObservableCollection<GridData> GetData()
            {
                ObservableCollection<GridData> data = new ObservableCollection<GridData>();
                data.Add(new GridData()
                {
                    Name = "John Doe",
                    Age = 30,
                    Male = true,
                    IsSelected = false
                });
                data.Add(new GridData()
                {
                    Name = "Jane Doe",
                    Age = 32,
                    Male = false,
                    IsSelected = false
                });
                data.Add(new GridData()
                {
                    Name = "Jason Smith",
                    Age = 54,
                    Male = true,
                    IsSelected = false
                });
                data.Add(new GridData()
                {
                    Name = "Kayli Jayne",
                    Age = 25,
                    Male = false,
                    IsSelected = false
                });
                return data;
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }
        } 
    }

    Any question on this issue, please let me know.

    Best Regards,

    Thursday, September 22, 2011 5:37 AM
  • Thai, you really need to read and understand the thread before your post.  The question is:

    How do I bind a stackpanel Visibility property to my list box item IsSelected property.  How are you going to do that without a converter?

    Ali, The reason why you are getting that error is that you can't use binding in a setter property of a style in Silverlight 4:

    http://social.msdn.microsoft.com/Forums/en-US/silverlightstart/thread/3b0f03e2-ab3e-4417-9134-91c3e47fee34#a94b9e56-df69-4633-89d8-b65dbdb51715

    Although you can in Silverlight 5:

    http://www.kunal-chowdhury.com/2011/05/binding-on-style-setter-in-silverlight.html

    So maybe Haixia is running Silverlight 5.

    Sunday, September 25, 2011 2:51 PM

All replies

  • which version of Silverlight?  If 5, you can use Ancestor RelativeSource binding to get a reference to the ListBoxItem which is the control you're trying to reference.  Otherwise, maybe you could get creative with a converter and walk up the tree until you find a ListBoxItem.

    Tuesday, September 20, 2011 6:54 PM
  • I'm still using Silverlight 4. 

     

    I guess I'll keep looking for a solution, since I can't upgrade at the moment.

    Tuesday, September 20, 2011 9:08 PM
  • Hi Ali,

    Below is my test code, and the StackPanel only be displayed for the selected item. You may have a try.

    .xaml

    <UserControl x:Class="BindingVisibility.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:myproject="clr-namespace:BindingVisibility" 
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">
    
        <UserControl.Resources>
            <myproject:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />     
        </UserControl.Resources>
        <Grid x:Name="LayoutRoot" Background="White">
           
            <ListBox Name="listBox1" Margin="0,0,0,0" >
                <ListBox.ItemContainerStyle>
                    <Style TargetType="ListBoxItem">
                        <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}" >
                        </Setter>
                    </Style>
                </ListBox.ItemContainerStyle>
    
                    <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Vertical"   >
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="This is where the person's info goes, picture, name, and stuff, the color of the row changes based on his status, and stuff like that" TextWrapping="Wrap" Height="100" Width="600"/>
                            </StackPanel>
                            <TextBlock Text="{Binding Name}" />
                            
                            <StackPanel Orientation="Horizontal" x:Name="buttonsPanel" Visibility="{Binding Path=IsSelected,Converter={StaticResource BooleanToVisibilityConverter},Mode=TwoWay}"   >
                                <RadioButton x:Name="presentButton"  Content="Present" Width="100" ClickMode="Press" IsTabStop="False"/>
                                <RadioButton x:Name="absentButton" Content="Absent" Width="100" ClickMode="Press" IsTabStop="False"/>
                                <RadioButton x:Name="excusedButton" Content="Excused" Width="100" ClickMode="Press" IsTabStop="False"/>
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </Grid>
    </UserControl>

    .cs

    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Collections.ObjectModel;
    using System.Windows.Data;
    using System.ComponentModel;
    
    namespace BindingVisibility
    {
        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();         
                listBox1.ItemsSource = GridData.GetData();
            }          
        }
    
        public class GridData : INotifyPropertyChanged
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public bool Male { get; set; }
            private bool isSelected;
    
            public bool IsSelected
            {
                get 
                { 
                    return isSelected;
                }
                set 
                { 
                    isSelected = value;
                    NotifyPropertyChanged("IsSelected");
                }
            }
    
            public static ObservableCollection<GridData> GetData()
            {
                ObservableCollection<GridData> data = new ObservableCollection<GridData>();
                data.Add(new GridData()
                {
                    Name = "John Doe",
                    Age = 30,
                    Male = true,
                    IsSelected = false
                });
                data.Add(new GridData()
                {
                    Name = "Jane Doe",
                    Age = 32,
                    Male = false,
                    IsSelected = false
                });
                data.Add(new GridData()
                {
                    Name = "Jason Smith",
                    Age = 54,
                    Male = true,
                    IsSelected = false
                });
                data.Add(new GridData()
                {
                    Name = "Kayli Jayne",
                    Age = 25,
                    Male = false,
                    IsSelected = false
                });
                return data;
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }
        } 
    }

    Any question on this issue, please let me know.

    Best Regards,

    Thursday, September 22, 2011 5:37 AM
  • Hi Haixia,

     

    Thanks for the reply.

    I tried to run your code, but ran into an exception when InitializeComponent is called:

    {System.NotSupportedException: Cannot set read-only property ''.
       at MS.Internal.XamlMemberInfo.SetValue(Object target, Object value)
       at MS.Internal.XamlManagedRuntimeRPInvokes.SetValue(XamlTypeToken inType, XamlQualifiedObject& inObj, XamlPropertyToken inProperty, XamlQualifiedObject& inValue)}

    It is on this line:

      <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}" >

    I'm not realy sure why.  According to the docs IsSelected is not a read only property.                   

     

    Thursday, September 22, 2011 5:40 PM
  • Hi Ali,

    I suspect that you may have missed somthing, such as a reference or namespace. I have upload my test project( BooleanToVisibilityConvertertest) to skydrive , you may have a look.

    Best Regards,

    Thursday, September 22, 2011 8:48 PM
  • I get the same exact error running your sample application.

    What version of Silverlight are you using?

    Thursday, September 22, 2011 9:44 PM
  • Hi Ali,

    I am using Silverlight 4, and have these installed: VS 2010, Microsoft Silverlight 4 Toolkit April 2010,Microsoft Silverlight 4 SDK.

    Best Regards,

    Thursday, September 22, 2011 9:49 PM
  • That's exactly what I'm using!  Wonder why it blows up on mine?

    Thursday, September 22, 2011 9:52 PM
  • Hi Ali,

    Do you have same issue when running other Silverlight applications? Please check if you have these three (VS 2010, Microsoft Silverlight 4 Toolkit April 2010 ,Microsoft Silverlight 4 SDK) installed.

    Best Regards,

    Thursday, September 22, 2011 9:58 PM
  • Nope, no problems with other Silverlight Apps. I double checked the version of the SDK and toolkit and they are the same as yours. And I'm using VS2010.
    Thursday, September 22, 2011 10:17 PM
  • Hi Ali,

    The test application I posted above indeed created at Silverlight 4 version. The issue is not arise at my side maybe have something to do with I have installed Silverlight 5 SDK on my machine.

    Binding in style setters allows bindings to be used within styles to reference other properties is a new feature of Silverlight 5. So I will suggest you to install Silverlight 5.

    If you really don't want to install Silverlight 5, you may try this Setter value binding helper.

    http://blogs.msdn.com/b/delay/archive/2009/11/02/as-the-platform-evolves-so-do-the-workarounds-better-settervaluebindinghelper-makes-silverlight-setters-better-er.aspx

    Best Regards,

    Thursday, September 22, 2011 11:04 PM
  • Hi, It is dependency no reason to use Converter. However ListBox is Visaul Tree so that you can bind to ElementName. private Visibility _adminButtonsVisibility; public Visibility AdminButtonsVisibility { get { return _adminButtonsVisibility; } set { if (_adminButtonsVisibility != value) { _adminButtonsVisibility = value; OnPropertyChanged("AdminButtonsVisibility"); } } }
    Friday, September 23, 2011 7:23 AM
  • private Visibility _adminButtonsVisibility;
            public Visibility AdminButtonsVisibility
            {
                get { return _adminButtonsVisibility; }
                set
                {
                    if (_adminButtonsVisibility != value)
                    {
                        _adminButtonsVisibility = value;
                        OnPropertyChanged("AdminButtonsVisibility");
                    }
                }
            }

    Friday, September 23, 2011 7:23 AM
  • Thai, you really need to read and understand the thread before your post.  The question is:

    How do I bind a stackpanel Visibility property to my list box item IsSelected property.  How are you going to do that without a converter?

    Ali, The reason why you are getting that error is that you can't use binding in a setter property of a style in Silverlight 4:

    http://social.msdn.microsoft.com/Forums/en-US/silverlightstart/thread/3b0f03e2-ab3e-4417-9134-91c3e47fee34#a94b9e56-df69-4633-89d8-b65dbdb51715

    Although you can in Silverlight 5:

    http://www.kunal-chowdhury.com/2011/05/binding-on-style-setter-in-silverlight.html

    So maybe Haixia is running Silverlight 5.

    Sunday, September 25, 2011 2:51 PM