Tag Archives: Windows 8.1

How to Draw a Diagonal Line Using Only XAML (and no path data)

I’ve been playing around with an app to maintain a score. The first thing that I wanted to do was to split the screen, but I wanted a diagonal split; similar to this:

phonescreen

There are a number of ways that this can be achieved; however, this is a method using only XAML. The same method will (I believe) work on Windows 8, WPF and Windows Phone.

First, split the screen into three rows or columns (which depends on how you want the orientation):

        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

This needs to be an odd number of rows / columns if you want the line to be central; additionally, an increased number of rows or columns will result in a smaller incline. Next, draw a transparent rectangle across the middle grid square:

        <Rectangle Name="Placeholder" Grid.Row="1" 
                   HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                   Opacity="0"/>

Finally, simply draw a line, binding the X2, Y2 values to the height and width of your rectangle:

        <Line Grid.Row="1" 
              X1="0" X2="{Binding ActualWidth, ElementName=Placeholder}"
              Y1="0" Y2="{Binding ActualHeight, ElementName=Placeholder}"
              StrokeThickness="2" Stroke="Blue"/>

Conclusion

I’m not saying the is the best, most efficient, or only way of doing this. However, it does mean that I can do it on both Windows Phone and Windows Store (and in WPF if I were so inclined) using a single shared project.

Binding IsSelected Method in the ListView Control in WinRT

Basically, it’s not possible. However, this is the best (and only that works) workaround that I found.

Subclass the Listview

I tried everything. Absolutely everything.

I tried straightforward binding – that doesn’t work for IsSelected.
I tried using WinRT Xaml Toolkit – didn’t work.
I tried using Setters – they don’t work for WinRT.

Finally, I came across this solution; here’s the listview subclass (stolen directly from here: http://stackoverflow.com/questions/15994021/listviewitem-isselected-binding-works-for-wpf-but-not-for-winrt):

    public class ListViewEx : ListView
    {
        protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
        {
            base.PrepareContainerForItemOverride(element, item);
            
            ListViewItem listItem = element as ListViewItem;
            Binding binding = new Binding();
            binding.Mode = BindingMode.TwoWay;
            binding.Source = item;
            binding.Path = new PropertyPath("IsSelected");
            listItem.SetBinding(ListViewItem.IsSelectedProperty, binding);
        }
    }

Obviously this does restrict the IsSelected property name. My class looks something like this:

    public class Person
    {
        public string Name { get; set; }
        …
    }

I didn’t want to add an IsSelected property to this; because it doesn’t directly relate to the entity. My solution was to wrap this inside a class such as this:

    public class SelectableItem<T> : INotifyPropertyChanged
    {
        private T _item;
        public T Item 
        {
            get { return _item; }
            set
            {
                _item = value;
                RaisePropertyChanged();
            }
        }

        private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                _isSelected = value;                
                RaisePropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged([CallerMemberName] string name = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
}

And build it like this:

                List<Person> population = GetPeople();
                SelectablePeople = new ObservableCollection<SelectableItem<Person>>(population
                    .Select(n => new SelectableItem<Person>() { Item = n, IsSelected = false }).ToList());

So, finally, bind the collection to the new subclassed listview like this:

        <controls:ListViewEx x:Name="ItemListView" Grid.Column="0" Grid.Row="1"
                        ItemsSource="{Binding SelectablePeople}"                        
                        SelectionMode="Multiple"                        
                        Width="Auto" Height="Auto" >

            <controls:ListViewEx.ItemTemplate>
                <DataTemplate x:Name="MyTemplate">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock                            
                            Text="{Binding Item.Name}"/>
                    </StackPanel>
                </DataTemplate>
            </controls:ListViewEx.ItemTemplate>

        </controls:ListViewEx>