Jan
Jan

Reputation: 11

Binding custom ItemsControl

I’m trying to create custom Itemscontrol class to display a group of different shapes. To speed up process, I have reused source code from CodeProject (WPF Diagram Designer - Part 4) where all implementation is done but shapes are added from XAML code. For my purposes, I need to add them from code behind (dynamically) so I bound custom Itemscontrol to list of ObservableCollection. Now, instead of shapes be presented like this:

enter image description here

I get something like this:

enter image description here

Can somebody tell me what I’m doing wrong? Any help will be appreciated. Thanks in advance.

XAML:

<s:Toolbox x:Key="FlowChartStencils" ItemsSource="{Binding ElementName=MyDesigner,    Path=ToolboxDataItems}" ItemTemplate="{StaticResource toolboxItemTemplate}" ItemSize="190,150" SnapsToDevicePixels="True"   ScrollViewer.HorizontalScrollBarVisibility="Disabled">
</s:Toolbox>

<DataTemplate x:Key="toolboxItemTemplate">        
    <Grid Margin="5,5,5,5">            
        <Path Style="{StaticResource Process}">
            <s:DesignerItem.DragThumbTemplate>
                <ControlTemplate>
                    <Path Style="{StaticResource Process_DragThumb}"/>
                </ControlTemplate>
            </s:DesignerItem.DragThumbTemplate>
        </Path>            
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="  {Binding Title}" IsHitTestVisible="False" FontWeight="Bold"/>            
    </Grid>            
 </DataTemplate>

<Style x:Key="Process" TargetType="Path" BasedOn="{StaticResource FlowChartItemStyle}">
    <Setter Property="Data" Value="M 0,0 H 60 V40 H 0 Z"/>
</Style>

 <Style x:Key="Process_DragThumb" TargetType="Path" BasedOn="{StaticResource Process}">
    <Setter Property="IsHitTestVisible" Value="true"/>
    <Setter Property="Fill" Value="Transparent"/>
    <Setter Property="Stroke" Value="Transparent"/>
</Style>

<Style x:Key="FlowChartItemStyle" TargetType="Path">
    <Setter Property="Fill" Value="{StaticResource ItemBrush}"/>
    <Setter Property="Stroke" Value="{StaticResource ItemStroke}"/>
    <Setter Property="StrokeThickness" Value="1"/>
    <Setter Property="StrokeLineJoin" Value="Round"/>
    <Setter Property="Stretch" Value="Fill"/>
    <Setter Property="IsHitTestVisible" Value="False"/>
    <Setter Property="SnapsToDevicePixels" Value="True"/>
</Style>

<Brush x:Key="ItemStroke">#FFD69436</Brush>

<LinearGradientBrush x:Key="ItemBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
    <GradientStop Color="#FAFBE9" Offset="0" />
    <GradientStop Color="Orange" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>

Code behind:

// Implements ItemsControl for ToolboxItems    
public class Toolbox : ItemsControl
{
    // Defines the ItemHeight and ItemWidth properties of
    // the WrapPanel used for this Toolbox
    public Size ItemSize
    {
        get { return itemSize; }
        set { itemSize = value; }
    }
    private Size itemSize = new Size(50, 50);

    // Creates or identifies the element that is used to display the given item.        
     protected override DependencyObject GetContainerForItemOverride()
    {
         return new ToolboxItem();
    }

    // Determines if the specified item is (or is eligible to be) its own container.        
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
       return (item is ToolboxItem);
    }
}
// Represents a selectable item in the Toolbox/>.
public class ToolboxItem : ContentControl
{
    …
}

public class ToolboxDataItem : DependencyObject
{
    public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }

    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.Register( "Title", typeof( string ),
        typeof(ToolboxDataItem), new UIPropertyMetadata(""));

    public ToolboxDataItem(string title)
    {
        Title = title;
    }
}

public partial class DesignerCanvas : Canvas
{
    private ObservableCollection<ToolboxDataItem> toolboxDataItems = new ObservableCollection<ToolboxDataItem>();
    public ObservableCollection<ToolboxDataItem> ToolboxDataItems
    {
        get { return toolboxDataItems; }
    }

    public DesignerCanvas()
    {
        ToolboxDataItem toolboxDataItem = new ToolboxDataItem("123");
        ToolboxDataItems.Add(toolboxDataItem );
        toolboxDataItem = new ToolboxDataItem("456");
        ToolboxDataItems.Add(toolboxDataItem );
    }              
}   

MyDesigner:

<s:DesignerCanvas Focusable="true" x:Name="MyDesigner"
                  Background="{StaticResource WindowBackgroundBrush}" FocusVisualStyle="{x:Null}"
                  ContextMenu="{StaticResource DesignerCanvasContextMenu}"/>

Upvotes: 1

Views: 1102

Answers (1)

PPPereira
PPPereira

Reputation: 91

So I started by trying to get an app going with the code you shared but the styles were all in an incorrect order, so after the styles were set correctly I got arround to an example like this:

 <Window.Resources>
    <ResourceDictionary>

        <Brush x:Key="ItemStroke">#FFD69436</Brush>

        <LinearGradientBrush x:Key="ItemBrush" StartPoint="0,0" EndPoint="0,1">
            <LinearGradientBrush.GradientStops>
                <GradientStop Color="#FAFBE9" Offset="0" />
                <GradientStop Color="Orange" Offset="1" />
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>

        <Style x:Key="FlowChartItemStyle" TargetType="Path">
            <Setter Property="Fill" Value="{StaticResource ItemBrush}"/>
            <Setter Property="Stroke" Value="{StaticResource ItemStroke}"/>
            <Setter Property="StrokeThickness" Value="1"/>
            <Setter Property="StrokeLineJoin" Value="Round"/>
            <Setter Property="Stretch" Value="Fill"/>
            <Setter Property="IsHitTestVisible" Value="False"/>
            <Setter Property="SnapsToDevicePixels" Value="True"/>
        </Style>

        <Style x:Key="Process" TargetType="Path" BasedOn="{StaticResource FlowChartItemStyle}">
            <Setter Property="Data" Value="M 0,0 H 60 V40 H 0 Z"/>
        </Style>

        <DataTemplate x:Key="toolboxItemTemplate">
            <Grid Margin="5,5,5,5">
                <Path Style="{StaticResource Process}">
                </Path>
                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Title}" IsHitTestVisible="False" FontWeight="Bold"/>
            </Grid>
        </DataTemplate>

        <Style x:Key="Process_DragThumb" TargetType="Path" BasedOn="{StaticResource Process}">
            <Setter Property="IsHitTestVisible" Value="true"/>
            <Setter Property="Fill" Value="Transparent"/>
            <Setter Property="Stroke" Value="Transparent"/>
        </Style>

    </ResourceDictionary>
</Window.Resources>
<Grid>
    <ItemsControl Background="Yellow"
                            ItemsSource="{Binding ToolboxDataItems}" 
                            ItemTemplate="{StaticResource toolboxItemTemplate}"
                            SnapsToDevicePixels="True"  
                      ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    </ItemsControl>
</Grid>

So if you check this example to yours then your problem might be in one of two places:

1) The Text binding of the TextBlock (notice the space before the {):

2) Or the Path inside the ItemsSource binding of the toolbox

<s:Toolbox x:Key="FlowChartStencils" ItemsSource="{Binding ElementName=MyDesigner,    Path=ToolboxDataItems}" ItemTemplate="{StaticResource toolboxItemTemplate}" ItemSize="190,150" SnapsToDevicePixels="True"   ScrollViewer.HorizontalScrollBarVisibility="Disabled">

Here try something like ItemsSource="{Binding ToolboxDataItems, ElementName=MyDesigner}"

Upvotes: 1

Related Questions