Same XAML Silverlight and WPF – different result

I did not know the following would produce different results in WPF and Silverlight

<Grid>
        <TextBlock Text=”{Binding RelativeSource={RelativeSource Self}, Path=Tag}” Tag=”hello”/>
    </Grid>

In WPF, you see “Hello”. In silverlight you dont see anything

The following XAML produces same result in WPF and Silverlight

<Grid>
        <TextBlock Tag=”hello” Text=”{Binding RelativeSource={RelativeSource Self}, Path=Tag}” />
    </Grid>

ListBox and scrolling

When the listbox is bound to some data and when the data changes we may want to make the first item in the list visible.  That is not the default behaviour and ScrollIntoView(Item[0]) wont work. here is a way to reset the scrollposition

In the sample, I had the listbox’s  are bound to 200 items and when the button is clicked I set the items to 20. the listbox on the left shows the default behaviour , the listbox on the right  has the ScrollViewer position changed to show the first item  listbox scrolling
update: Looks like this method still has issues when the number of items changes from a very low number to  high number where the scrollbar appears and disappears as pointed out in this post. May be a bug?

update 2: Mog Liang (Microsoft Online Community Support) says “This is an known issue caused by ListBox virtualization. Currently, an workaround is replace VirtualizingStackPanel with StackPanel, however, this will drop the listbox performance.”

Here is the XAML and codebehind used in the sample

<Grid x:Name=”LayoutRoot” Margin=”5″>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            </Grid.ColumnDefinitions>
      <Button Content=”set to 20 items” Height=”28″ Width=”100″  HorizontalAlignment=”Right” Click=”Button_Click”/>
            <ListBox Grid.Column=”1″  Height=”200″ x:Name=”list1″ ItemsSource=”{Binding MyList}”/>
        <ListBox Grid.Column=”2″  Height=”200″ x:Name=”list2″ ItemsSource=”{Binding MyList}”/>
    </Grid>

 

public partial class MainPage : UserControl, INotifyPropertyChanged
    {
        public IEnumerable<string> MyList { get; set; }
        public MainPage()
        {
            InitializeComponent();
            MyList = Enumerable.Range(0, 200).Select(i => “Item..” + i.ToString()).ToList();
            this.DataContext = this;
           
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MyList = Enumerable.Range(0, 20).Select(i => “Item..” + i.ToString()).ToList();
            NotifyPropertyChanged(“MyList”);
            ScrollViewer sv = GetChild<ScrollViewer>(list2);
            sv.ScrollToVerticalOffset(0);
        }

        public static T GetChild<T>(DependencyObject obj) where T : DependencyObject
        {
            DependencyObject child = null; for (Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child.GetType() == typeof(T))
                {
                    break;
                }
                else if (child != null)
                {
                    child = GetChild<T>(child);
                    if (child != null && child.GetType() == typeof(T))
                    {
                        break;
                    }
                }
            }
            return child as T;
        }
        #region INotifyPropertyChanged Members

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

       
        #endregion
    }