Specifying a binding for Tile.DisplayIndex causes exception

7 posts, 0 answers
  1. Bjorn Inge
    Bjorn Inge avatar
    1 posts
    Member since:
    Oct 2013

    Posted 15 Nov 2013 Link to this post

    Hello Telerik,

    I'm trying to specify a binding on a tile's displayindex through a style. For some reason i get an exception stating:

    System.ArgumentNullException occurred
      HResult=-2147467261
      Message=Value cannot be null.
    Parameter name: property
      Source=PresentationFramework
      ParamName=property
      StackTrace:
           at System.Windows.Setter.CheckValidProperty(DependencyProperty property)
      InnerException: 

    This is my style for the tiles:

    <!-- Tile Style -->
       
    <Style TargetType="{x:Type telerik:Tile}">
            <Setter Property="Background">
    <Setter.Value>
                    <LinearGradientBrush>
                       <GradientStop Color="{Binding RelativeSource={RelativeSource AncestorType={x:Type telerik:Tile}, Mode=FindAncestor}, Path=Content.Color.StartColor}" Offset="0.0" />
                       <GradientStop Color="{Binding RelativeSource={RelativeSource AncestorType={x:Type telerik:Tile}, Mode=FindAncestor}, Path=Content.Color.EndColor}" Offset="1.0" />
                    </LinearGradientBrush>
                </Setter.Value>
           </Setter>
           <Setter Property="TileType" Value="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Content.Size, Converter={StaticResource tileTypeConverter}}" />
           <Setter Property="DisplayIndex" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type telerik:Tile}, Mode=FindAncestor}, Path=Content.DisplayIndex, Mode=OneTime}" />
    </Style>

    Am I doing something obviously wrong?
  2. Maya
    Admin
    Maya avatar
    4062 posts

    Posted 18 Nov 2013 Link to this post

    Hello Bjorn,

    Currently, DisplayIndex property of the tile is not a dependency one and you cannot bind it. That is why you are getting such error. We will consider changing it to dependency property, but for the time being it is just a regular CLR property.   

    Regards,
    Maya
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  3. UI for WPF is Visual Studio 2017 Ready
  4. Muhammad Ummar
    Muhammad Ummar avatar
    26 posts
    Member since:
    Jul 2012

    Posted 27 May 2014 in reply to Maya Link to this post

    Hello Maya,

    I need to save the DisplayIndex to database so I can set a position of Tile next time it gets loaded. I want to know how can I update the ViewModel's property when DisplayIndex is changed using Drag and Drop operation? I know it is not a dependency property so data binding wouldn't be possible, any other workaround for this problem? 

    Regards
    Ummar
  5. Boris
    Admin
    Boris avatar
    276 posts

    Posted 30 May 2014 Link to this post

    Hello Ummar,

    We will need a little more time to think of a possible workaround. We will get back to you as soon as possible.

    Regards,
    Boris Penev
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
  6. Boris
    Admin
    Boris avatar
    276 posts

    Posted 30 May 2014 Link to this post

    Hello Ummar,

    A possible approach for fulfilling your requirement is to attach a OnDrop() handler to the TileList by using the DragDropManager.AddDropHandler() method. In that handler you will need to get all the Tiles of the TileList by using the  ChildrenOfType<Tile>() extension method. Then get the business object for each tile by using its DataContext property and set DisplayIndex property of your Business object to the DisplayIndex property of the Tile.
    In order to load initially in any particular order the tiles, you can use the AutoGeneratingTile event of the TileList.

    Please examine the attached a sample project that demonstrates the suggested approach and let us know if this helps.

    Regards,
    Boris Penev
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
  7. Muhammad Ummar
    Muhammad Ummar avatar
    26 posts
    Member since:
    Jul 2012

    Posted 05 Jun 2014 Link to this post

    Hello Boris,

    Thanks for your reply and helpful code example, it worked. THANKS.

    But my scenario is little bit different as I am also using the Grouping of tiles, the approach you described worked fine in grouping case as well. But the DisplayIndex printed in OnDrop event handler are not as expected, in fact they contain the wrong values. but visually every thing is fine. Just for my understanding I have updated your project with Group functionality, and added 8 more tiles along with 4 your tiles (means total 12 tiles) divided in 3 groups. So the DisplayIndex renage in 0-11. but when I drag/drop any tile the printed DisplayIndex also contains the wrong values even 26 and 27, which is not possible. Following are the code updates so you can test
     
     The Business object is

    001./// <summary>
    002.    /// A football club.
    003.    /// </summary>
    004.    public class Club : INotifyPropertyChanged
    005.    {
    006.        public event PropertyChangedEventHandler PropertyChanged;
    007. 
    008.        private string name;
    009.        private int? displayIndex;
    010. 
    011.        public int? DisplayIndex
    012.        {
    013.            get { return this.displayIndex; }
    014.            set
    015.            {
    016.                if (value != this.displayIndex)
    017.                {
    018.                    this.displayIndex = value;
    019.                    this.OnPropertyChanged("DisplayIndex");
    020.                }
    021.            }
    022.        }
    023. 
    024.        public string Name
    025.        {
    026.            get { return this.name; }
    027.            set
    028.            {
    029.                if (value != this.name)
    030.                {
    031.                    this.name = value;
    032.                    this.OnPropertyChanged("Name");
    033.                }
    034.            }
    035.        }
    036. 
    037.        private string _tileGroup;
    038. 
    039.        public string TileGroup
    040.        {
    041.            get { return _tileGroup; }
    042.            set
    043.            {
    044.                _tileGroup = value;
    045.                OnPropertyChanged("TileGroup");
    046.            }
    047.        }
    048.         
    049. 
    050.        public Club()
    051.        {
    052. 
    053.        }
    054. 
    055.        public Club(string name, int displayIndex, string groupHeader)
    056.        {
    057.            this.name = name;
    058.            this.displayIndex = displayIndex;
    059.            TileGroup = groupHeader;
    060.        }
    061. 
    062.        protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
    063.        {
    064.            PropertyChangedEventHandler handler = this.PropertyChanged;
    065.            if (handler != null)
    066.            {
    067.                handler(this, args);
    068.            }
    069.        }
    070. 
    071.        private void OnPropertyChanged(string propertyName)
    072.        {
    073.            this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    074.        }
    075. 
    076.        public override string ToString()
    077.        {
    078.            return this.Name;
    079.        }
    080. 
    081.        public static ObservableCollection<Club> GetClubs()
    082.        {
    083.            ObservableCollection<Club> clubs = new ObservableCollection<Club>();
    084.            Club club;
    085. 
    086.            // Liverpool
    087.            club = new Club("Liverpool", 3, "Group1");
    088.            clubs.Add(club);
    089. 
    090.            // Manchester Utd.
    091.            club = new Club("Manchester Utd.", 2, "Group1");
    092.            clubs.Add(club);
    093. 
    094.            // Chelsea
    095.            club = new Club("Chelsea", 0, "Group1");
    096.            clubs.Add(club);
    097. 
    098.            // Arsenal
    099.            club = new Club("Arsenal", 1, "Group1");
    100.            clubs.Add(club);
    101. 
    102.            // Liverpool
    103.            club = new Club("Liverpool-Group2", 7, "Group2");
    104.            clubs.Add(club);
    105. 
    106.            // Manchester Utd.
    107.            club = new Club("Manchester Utd-Group2.", 6, "Group2");
    108.            clubs.Add(club);
    109. 
    110.            // Chelsea
    111.            club = new Club("Chelsea-Group2", 4, "Group2");
    112.            clubs.Add(club);
    113. 
    114.            // Arsenal
    115.            club = new Club("Arsenal-Group2", 5, "Group2");
    116.            clubs.Add(club);
    117. 
    118.            // Liverpool
    119.            club = new Club("Liverpool-Group3", 11, "Group3");
    120.            clubs.Add(club);
    121. 
    122.            // Manchester Utd.
    123.            club = new Club("Manchester Utd-Group3.", 10, "Group3");
    124.            clubs.Add(club);
    125. 
    126.            // Chelsea
    127.            club = new Club("Chelsea-Group3", 8, "Group3");
    128.            clubs.Add(club);
    129. 
    130.            // Arsenal
    131.            club = new Club("Arsenal-Group3", 9, "Group3");
    132.            clubs.Add(club);
    133. 
    134.            return clubs;
    135.        }
    136.    }


    The updated Main window code is 
    01.<Window x:Class="RadTileList_WPF_DisplayIndex.MainWindow"
    04.        xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
    05.        xmlns:my="clr-namespace:RadTileList_WPF_DisplayIndex"
    06.        Title="MainWindow" Height="700" Width="700">
    07.    <Window.Resources>
    08.        <my:MyViewModel x:Key="MyViewModel"/>
    09.    </Window.Resources>
    10.    <Grid DataContext="{StaticResource MyViewModel}">
    11.        <Grid.RowDefinitions>
    12.            <RowDefinition Height="*"/>
    13.            <RowDefinition Height="Auto" />
    14.        </Grid.RowDefinitions>
    15.        <telerik:RadTileList x:Name="tileList"
    16.                             ItemsSource="{Binding Clubs}"
    17.                             AutoGeneratingTile="tileList_AutoGeneratingTile"
    18.                             ScrollViewer.HorizontalScrollBarVisibility="Visible">
    19.            <telerik:RadTileList.GroupTemplate>
    20.                <DataTemplate>
    21.                    <TextBlock Margin="0,0,0,10" Text="{Binding}" FontSize="16"></TextBlock>
    22.                </DataTemplate>
    23.            </telerik:RadTileList.GroupTemplate>
    24.            </telerik:RadTileList>
    25.    </Grid>
    26.</Window>

    and finally the code behind for Main window is 

    01.using System;
    02.using System.Collections.Generic;
    03.using System.Linq;
    04.using System.Text;
    05.using System.Windows;
    06.using System.Windows.Controls;
    07.using System.Windows.Data;
    08.using System.Windows.Documents;
    09.using System.Windows.Input;
    10.using System.Windows.Media;
    11.using System.Windows.Media.Imaging;
    12.using System.Windows.Navigation;
    13.using System.Windows.Shapes;
    14.using Telerik.Windows.Controls;
    15.using System.Diagnostics;
    16.using Telerik.Windows.DragDrop;
    17. 
    18.namespace RadTileList_WPF_DisplayIndex
    19.{
    20.    /// <summary>
    21.    /// Interaction logic for MainWindow.xaml
    22.    /// </summary>
    23.    public partial class MainWindow : Window
    24.    {
    25.        public MainWindow()
    26.        {
    27.            InitializeComponent();
    28.            DragDropManager.AddDropHandler(this.tileList, OnDrop);
    29.        }
    30. 
    31.        private void OnDrop(object sender, Telerik.Windows.DragDrop.DragEventArgs e)
    32.        {
    33.            e.Handled = true;
    34.            var tiles = this.tileList.ChildrenOfType<Tile>();
    35.            foreach (Tile tile in tiles)
    36.            {
    37.                Club club = tile.DataContext as Club;
    38.                club.DisplayIndex = tile.DisplayIndex;
    39.                Debug.WriteLine("Name: " + club.Name + "; DisplayIndex: " + club.DisplayIndex);
    40.            }
    41.        }
    42. 
    43.        private void tileList_AutoGeneratingTile(object sender, AutoGeneratingTileEventArgs e)
    44.        {
    45.            e.Tile.DisplayIndex = (e.Tile.DataContext as Club).DisplayIndex;
    46.            e.Tile.Group = (e.Tile.DataContext as Club).TileGroup;
    47.        }
    48.    }
    49.}

    Run the code and Drag any tile and Drop it to some other group, on the debug console you will see the wrong entries of DisplayIndex. and each time you drag tiles you will see DisplayIndex increasing.

    Just a reminder that visually every thing works fine and on next reload the tiles appear in correct position. but I am wondering about wrong values of DisplayIndex? Could you please clarify?
  8. Boris
    Admin
    Boris avatar
    276 posts

    Posted 09 Jun 2014 Link to this post

    Hello Ummar,

    Thank you for reporting this issue. We reviewed the TileList control and we can confirm that the reported behavior is actually a bug. We logged it in our feedback portal where you can track its status. We also updated your Telerik account points as a thanks for your cooperation in reporting this issue.

    Regards,
    Boris Penev
    Telerik
     
    Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
     
Back to Top
UI for WPF is Visual Studio 2017 Ready