How to set the OverflowMode of RadButton inside ItemTemplate?

5 posts, 0 answers
  1. Art
    Art avatar
    23 posts
    Member since:
    Apr 2015

    Posted 23 Jun Link to this post

    Seems it does not work for me:

    <UserControl.Resources>
        <DataTemplate DataType="vm:MenuItemViewModel" x:Key="ToolBarItemTemplate">
            <c:TemplateSelector TemplateKey="{Binding MenuItemType}" Content="{Binding}">
                <c:TemplateItem x:Key="{t:Static Member=vm:MenuItemType.Button}">
                    <t:RadButton IsEnabled="{Binding IsEnabled}" Content="{Binding Text}"
                                 Command="{Binding Command}" ToolTipService.ToolTip="{Binding ToolTip}" t:RadToolBar.OverflowMode="{Binding OverflowMode}" />
                </c:TemplateItem>
                <c:TemplateItem x:Key="{t:Static Member=vm:MenuItemType.Checkbox}">
                    <t:RadToggleButton IsEnabled="{Binding IsEnabled}" Content="{Binding Text}"
                                       Command="{Binding Command}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}"
                                       ToolTipService.ToolTip="{Binding ToolTip}" t:RadToolBar.OverflowMode="{Binding OverflowMode}" />
                </c:TemplateItem>
            </c:TemplateSelector>
        </DataTemplate>
    </UserControl.Resources>
     
    <t:RadToolBarTray e:RadToolBarTrayExtensions.ItemsSource="{Binding Items}" VerticalAlignment="Center">
        <t:RadToolBarTray.ItemTemplate>
            <DataTemplate DataType="vm:MenuViewModel">
                <t:RadToolBar ItemsSource="{Binding Items}" ItemTemplate="{StaticResource ToolBarItemTemplate}" />
            </DataTemplate>
        </t:RadToolBarTray.ItemTemplate>
    </t:RadToolBarTray>

    This t:RadToolBar.OverflowMode="{Binding OverflowMode}" is ignored. Even if I set it directly to "Never" or "Always"...

  2. Art
    Art avatar
    23 posts
    Member since:
    Apr 2015

    Posted 23 Jun in reply to Art Link to this post

    It works only in this case with the direct content:

        <t:RadToolBarTray e:RadToolBarTrayExtensions.ItemsSource="{Binding Items}" VerticalAlignment="Center">
            <t:RadToolBarTray.ItemTemplate>
                <DataTemplate DataType="vm:MenuViewModel">
    <!--                <t:RadToolBar ItemsSource="{Binding Items}" ItemTemplate="{StaticResource ToolBarItemTemplate}" />-->
                    <t:RadToolBar>
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="Never" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="Never" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="Never" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="Never" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="AsNeeded" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="AsNeeded" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="AsNeeded" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="AsNeeded" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="AsNeeded" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="AsNeeded" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="AsNeeded" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="AsNeeded" />
                         
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="Always" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="Always" />
                        <t:RadButton Content="Button!" t:RadToolBar.OverflowMode="Always" />
     
                    </t:RadToolBar>
                </DataTemplate>
            </t:RadToolBarTray.ItemTemplate>
        </t:RadToolBarTray>

     

  3. DevCraft banner
  4. Art
    Art avatar
    23 posts
    Member since:
    Apr 2015

    Posted 24 Jun in reply to Art Link to this post

    I has adapted the next code for RadToolBar from this post:

    It use attached ItemsSource instead of RadToolBar's ItemsSource and manually sets the OverflowMode to itemContainer from RadToolBar.ItemContainerStyle.

    public class RadToolBarExtensions
    {
        private static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.RegisterAttached("ItemsSource", typeof(IEnumerable),
                typeof(RadToolBarExtensions), new PropertyMetadata(OnItemsSourceChanged));
     
        private static readonly DependencyProperty ToolBarExtensionsProperty =
            DependencyProperty.RegisterAttached("ToolBarExtensions", typeof(RadToolBarExtensions),
                typeof(RadToolBarExtensions), new PropertyMetadata(null));
     
        private readonly RadToolBar _toolBar;
     
        private RadToolBarExtensions(RadToolBar toolBar)
        {
            _toolBar = toolBar;
        }
     
        public static IEnumerable GetItemsSource(DependencyObject d)
        {
            return (IEnumerable)d.GetValue(ItemsSourceProperty);
        }
     
        public static void SetItemsSource(DependencyObject d, IEnumerable value)
        {
            d.SetValue(ItemsSourceProperty, value);
        }
     
        private static RadToolBarExtensions GetToolBarExtensions(DependencyObject d)
        {
            return (RadToolBarExtensions)d.GetValue(ToolBarExtensionsProperty);
        }
     
        private static void SetToolBarExtensions(DependencyObject d, RadToolBarExtensions value)
        {
            d.SetValue(ToolBarExtensionsProperty, value);
        }
     
        private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var toolBar = (RadToolBar)d;
            var extensions = GetToolBarExtensions(toolBar);
     
            if (extensions == null)
            {
                extensions = new RadToolBarExtensions(toolBar);
                SetToolBarExtensions(toolBar, extensions);
            }
     
            if (e.OldValue != null)
            {
                toolBar.Items.Clear();
     
                var ncc = e.OldValue as INotifyCollectionChanged;
     
                if (ncc != null)
                    ncc.CollectionChanged -= extensions.OnCollectionChanged;
            }
     
            if (e.NewValue != null)
            {
                foreach (var item in (IEnumerable)e.NewValue)
                {
                    toolBar.Items.Add(GenerateItemContainer(item, toolBar.ItemTemplate, toolBar.ItemContainerStyle));
                }
     
                var ncc = e.NewValue as INotifyCollectionChanged;
     
                if (ncc != null)
                    ncc.CollectionChanged += extensions.OnCollectionChanged;
            }
        }
     
        // OverflowMode settings is here.
        //
        private static FrameworkElement GenerateItemContainer(object dataItem, DataTemplate template, Style itemContainerStyle)
        {
            if (template == null)
                throw new ArgumentNullException("template");
     
            var itemContainer = (FrameworkElement) template.LoadContent();
     
            itemContainer.DataContext = dataItem;
            itemContainer.Style = itemContainerStyle;
     
            if (itemContainerStyle != null)
            {
                var overflowModeSetter =
                    itemContainerStyle.Setters.OfType<Setter>().FirstOrDefault(
                        x => x.Property == RadToolBar.OverflowModeProperty);
     
                if (overflowModeSetter != null)
                {
                    var value = overflowModeSetter.Value;
     
                    if (value is Binding)
                        itemContainer.SetBinding(RadToolBar.OverflowModeProperty, (Binding) overflowModeSetter.Value);
                    else if (value is OverflowMode)
                        RadToolBar.SetOverflowMode(itemContainer, (OverflowMode) value);
                }
            }
     
            return itemContainer;
        }
     
        private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.OldItems != null)
            {
                foreach (var oldItem in e.OldItems)
                {
                    var itemContainer =
                        _toolBar.Items.OfType<FrameworkElement>().FirstOrDefault(x => x.DataContext == oldItem);
     
                    if (itemContainer != null)
                        _toolBar.Items.Remove(itemContainer);
                }
            }
     
            if (e.NewItems != null)
            {
                foreach (var newItem in e.NewItems)
                {
                    _toolBar.Items.Add(GenerateItemContainer(newItem, _toolBar.ItemTemplate, _toolBar.ItemContainerStyle));
                }
            }
     
            if (e.Action == NotifyCollectionChangedAction.Reset)
                _toolBar.Items.Clear();
        }
    }

    Usage:

    <t:RadToolBarTray e:RadToolBarTrayExtensions.ItemsSource="{Binding Items}" VerticalAlignment="Center">
            <t:RadToolBarTray.ItemTemplate>
                <DataTemplate DataType="vm:MenuViewModel">
                    <t:RadToolBar e:RadToolBarExtensions.ItemsSource="{Binding Items}" ItemTemplate="{StaticResource ToolBarItemTemplate}">
                        <t:RadToolBar.ItemContainerStyle>
                            <Style TargetType="DependencyObject">
                                <Setter Property="t:RadToolBar.OverflowMode" Value="{Binding OverflowMode}" />
                            </Style>
                        </t:RadToolBar.ItemContainerStyle>
                    </t:RadToolBar>
                </DataTemplate>
            </t:RadToolBarTray.ItemTemplate>
        </t:RadToolBarTray>

    Maybe there is more simple built-in solution of this problem? :)

  5. Martin
    Admin
    Martin avatar
    1101 posts

    Posted 27 Jun Link to this post

    Hello Art,

    Thank you for sharing your solution.

    The described behavior is a limitation of the control and there is no built-in solution which I can offer you. I logged it in our feedback portal. I also updated your Telerik points as a small gesture of gratitude for reporting this.

    Regards,
    Martin
    Telerik
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
  6. Art
    Art avatar
    23 posts
    Member since:
    Apr 2015

    Posted 27 Jun Link to this post

    Modified solution, respects the ItemsControl.ItemTemplateSelector if ItemsControl.ItemTemplate is not setted.

    Found strange issue:

    - ToolBarContainerStyleSelector in Windows8Touch theme style of RadToolBar doesn't apply it's defined ContainerStyle to type "RadToolBarSeparator", when RadToolBar.ItemContainerStyle is setted to style with "OverflowMode" as writen before. But it applies styles of ToolBarRadButtonStyle and ToolBarRadToggleButtonStyle anyway as defined in theme (current ItemContainerStyle ignored for buttons within this extension).

    So, I moved setter from style to the attached RadToolBarExtensions.ItemOverflowModeProperty, which supports binding (current item's context).

    Magically, now it works fine:

    public class RadToolBarExtensions
    {
        private static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.RegisterAttached("ItemsSource", typeof(IEnumerable),
                typeof(RadToolBarExtensions), new PropertyMetadata(OnItemsSourceChanged));
     
        private static readonly DependencyProperty ItemOverflowModeProperty =
            DependencyProperty.RegisterAttached("ItemOverflowMode", typeof (object),
                typeof (RadToolBarTrayExtensions), new PropertyMetadata(null));
     
     
        private static readonly DependencyProperty ToolBarExtensionsProperty =
            DependencyProperty.RegisterAttached("ToolBarExtensions", typeof(RadToolBarExtensions),
                typeof(RadToolBarExtensions), new PropertyMetadata(null));
     
        private readonly RadToolBar _toolBar;
     
        private RadToolBarExtensions(RadToolBar toolBar)
        {
            _toolBar = toolBar;
        }
     
        public static IEnumerable GetItemsSource(DependencyObject d)
        {
            return (IEnumerable)d.GetValue(ItemsSourceProperty);
        }
     
        public static void SetItemsSource(DependencyObject d, IEnumerable value)
        {
            d.SetValue(ItemsSourceProperty, value);
        }
     
        public static object GetItemOverflowMode(DependencyObject d)
        {
            return d.GetValue(ItemOverflowModeProperty);
        }
     
        public static void SetItemOverflowMode(DependencyObject d, object value)
        {
            d.SetValue(ItemOverflowModeProperty, value);
        }
     
        private static RadToolBarExtensions GetToolBarExtensions(DependencyObject d)
        {
            return (RadToolBarExtensions)d.GetValue(ToolBarExtensionsProperty);
        }
     
        private static void SetToolBarExtensions(DependencyObject d, RadToolBarExtensions value)
        {
            d.SetValue(ToolBarExtensionsProperty, value);
        }
     
        private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var toolBar = (RadToolBar)d;
            var extensions = GetToolBarExtensions(toolBar);
     
            if (extensions == null)
            {
                extensions = new RadToolBarExtensions(toolBar);
                SetToolBarExtensions(toolBar, extensions);
            }
     
            if (e.OldValue != null)
            {
                toolBar.Items.Clear();
     
                var ncc = e.OldValue as INotifyCollectionChanged;
     
                if (ncc != null)
                    ncc.CollectionChanged -= extensions.OnCollectionChanged;
            }
     
            if (e.NewValue != null)
            {
                foreach (var item in (IEnumerable)e.NewValue)
                {
                    toolBar.Items.Add(GenerateItemContainer(item, toolBar));
                }
     
                var ncc = e.NewValue as INotifyCollectionChanged;
     
                if (ncc != null)
                    ncc.CollectionChanged += extensions.OnCollectionChanged;
            }
        }
     
        private static FrameworkElement GenerateItemContainer(object dataItem, ItemsControl toolBar)
        {
            var itemTemplate = toolBar.ItemTemplate;
            var itemTemplateSelector = toolBar.ItemTemplateSelector;
     
            if (itemTemplate == null && itemTemplateSelector != null)
                itemTemplate = itemTemplateSelector.SelectTemplate(dataItem, toolBar);
     
            if (itemTemplate == null)
                return null;
     
            var itemContainer = (FrameworkElement) itemTemplate.LoadContent();
            itemContainer.DataContext = dataItem;
     
            var overflowProperty = GetItemOverflowMode(toolBar);
     
            if (overflowProperty != null)
            {
                if (overflowProperty is Binding)
                    itemContainer.SetBinding(RadToolBar.OverflowModeProperty, (Binding) overflowProperty);
                else if (overflowProperty is OverflowMode)
                    RadToolBar.SetOverflowMode(itemContainer, (OverflowMode) overflowProperty);
            }
     
            return itemContainer;
        }
     
        private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.OldItems != null)
            {
                foreach (var oldItem in e.OldItems)
                {
                    var itemContainer =
                        _toolBar.Items.OfType<FrameworkElement>().FirstOrDefault(x => x.DataContext == oldItem);
     
                    if (itemContainer != null)
                        _toolBar.Items.Remove(itemContainer);
                }
            }
     
            if (e.NewItems != null)
            {
                foreach (var newItem in e.NewItems)
                {
                    _toolBar.Items.Add(GenerateItemContainer(newItem, _toolBar));
                }
            }
     
            if (e.Action == NotifyCollectionChangedAction.Reset)
                _toolBar.Items.Clear();
        }
    }

    Usage:

    <!-- fragment -->
            <c:ItemTemplateSelector x:Key="ToolBarItemTemplateSelector">
                <c:ItemTemplateRule DataType="vm:SeparatorMenuItem" DataTemplate="{StaticResource SeparatorMenuItemTemplate}" />
                <c:ItemTemplateRule DataType="vm:RadioMenuItemViewModel" DataTemplate="{StaticResource RadioMenuItemTemplate}" />
                <c:ItemTemplateRule DataType="vm:CheckMenuItemViewModel" DataTemplate="{StaticResource CheckMenuItemTemplate}" />
                <c:ItemTemplateRule DataType="vm:MenuItemViewModel" DataTemplate="{StaticResource MenuItemTemplate}" />
            </c:ItemTemplateSelector>
        </UserControl.Resources>
     
        <t:RadToolBarTray e:RadToolBarTrayExtensions.ItemsSource="{Binding Items}" VerticalAlignment="Center">
            <t:RadToolBarTray.ItemTemplate>
                <DataTemplate DataType="vm:MenuViewModel">
                    <t:RadToolBar e:RadToolBarExtensions.ItemOverflowMode="{Binding OverflowMode}"
                                  e:RadToolBarExtensions.ItemsSource="{Binding Items}" ItemTemplateSelector="{StaticResource ToolBarItemTemplateSelector}">
     
                    </t:RadToolBar>
                </DataTemplate>
            </t:RadToolBarTray.ItemTemplate>
        </t:RadToolBarTray>

    Hope it help to someone.
Back to Top
DevCraft banner