This is a migrated thread and some comments may be shown as answers.

How to set the OverflowMode of RadButton inside ItemTemplate?

4 Answers 106 Views
ToolBar
This is a migrated thread and some comments may be shown as answers.
Art
Top achievements
Rank 1
Art asked on 23 Jun 2016, 07:59 AM

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"...

4 Answers, 1 is accepted

Sort by
0
Art
Top achievements
Rank 1
answered on 23 Jun 2016, 08:14 AM

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>

 

0
Art
Top achievements
Rank 1
answered on 24 Jun 2016, 05:32 AM

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? :)

0
Martin Ivanov
Telerik team
answered on 27 Jun 2016, 01:55 PM
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.
0
Art
Top achievements
Rank 1
answered on 27 Jun 2016, 03:21 PM

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.
Tags
ToolBar
Asked by
Art
Top achievements
Rank 1
Answers by
Art
Top achievements
Rank 1
Martin Ivanov
Telerik team
Share this question
or