locked
Border for Canvas inside ItemsPanelTemplate! RRS feed

  • Question

  • Hi,

    I have a very unique problem.

    I have this XAML:

    <ListBox.ItemsPanel>
     <ItemsPanelTemplate>
     <local:MyCanvas Margin="20">
       <Canvas.Style>
        <Style TargetType="Canvas">
        <Setter Property="Background">
          <Style.Triggers>
          <DataTrigger Binding="{Binding Path= GRIDONOFF}" Value="True">
          <Setter Property="Background" Value="{Binding Value, Converter={StaticResource DoubleToVisulBrushConverter}, ElementName=mySlider}"/>
          </DataTrigger>
          </Style.Triggers>
          </Style>
         </Canvas.Style>
        </local:MyCanvas>                          
     </ItemsPanelTemplate>
    </ListBox.ItemsPanel>

    Converter:

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                if (value is double)
                {
                    var GridSize = (double)value;
    
                    
                    var rect = new Rectangle
                    {
                        Width = GridSize ,
                        Height = GridSize ,
                        Stroke = new SolidColorBrush(Colors.DarkGray),
                        StrokeThickness = 0.5,
                        StrokeDashArray = new DoubleCollection {1, GridSize * 4},
                        Fill =
                            (SolidColorBrush) ((new BrushConverter().ConvertFrom("#FF323337"))),
                        SnapsToDevicePixels = true
                    };
    
                    //Construct the VisualBrush
                    var brush = new VisualBrush
                    {
                        Viewbox = new Rect(0, 0, GridSize , layoutGridSize),
                        Viewport = new Rect(0, 0, GridSize , GridSize ),
                        TileMode = TileMode.Tile,
                        ViewboxUnits = BrushMappingMode.Absolute,
                        ViewportUnits = BrushMappingMode.Absolute,
                        Visual = rect
                    };
    
                    return brush;
                }
    

    Depending on the slider (that tells the grid cell size) I set the background of the Canvas (a grid is painted on it).

    Now I want to show a border around that grid to show the end of the drawing area.

    But because of the XAML structure and 

    ItemsPanelTemplate

    I cant add border or rectangle to the Canvas (Cant add children like that).

    And I dont think I can change that structure.

    So what is the possible solution here?


    Please Mark as Answered If this answers your question Or UnMark as Answered if it did not.
    Happy to Help :)
    My Site

    Monday, May 26, 2014 8:31 AM

Answers

  • Thank you for the support.

    I did it this way after some searching around on the internet:

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                if (values[0] is double)
                {
                    var GridSize = (double)values[0];
                    SolidColorBrush girdColor = DarkGray
                    
                   
                    var rect = new Rectangle
                    {
                        Width = GridSize ,
                        Height = GridSize ,
                        Stroke = girdColor,
                        StrokeThickness = 0.5,
                        StrokeDashArray = new DoubleCollection { 1, GridSize * 4 },
                        Fill =
                            (SolidColorBrush)((new BrushConverter().ConvertFrom("DarkGray")),
                        SnapsToDevicePixels = true
                    };
    
                    
                    var brush = new VisualBrush
                    {
                        Viewbox = new Rect(0, 0, GridSize , GridSize ),
                        Viewport = new Rect(0, 0, GridSize , GridSize ),
                        TileMode = TileMode.Tile,
                        ViewboxUnits = BrushMappingMode.Absolute,
                        ViewportUnits = BrushMappingMode.Absolute,
                        Visual = rect
                    };
    
                    
                    Size bounds = new Size(Math.Floor((double)values[1]) -1, Math.Floor((double)values[2]) -1);
                    var outerGrid = new DrawingBrush
                    {
                        Stretch = Stretch.None,
                        AlignmentX = AlignmentX.Left,
                        AlignmentY = AlignmentY.Top,
                        Drawing = new GeometryDrawing
                        {
                            Geometry = new RectangleGeometry(new Rect(bounds)),
                            Pen = new Pen(girdColor, Constants.LAYOUT_GRID_STROKE_THICKNESS),
                            Brush = brush
                        }
                    };
    
                    return outerGrid;
                }
    
                return null;
            }

    I added an outer rectangle with Canvas height and width as its bounds and internal brush as my previous grid brush.

    This works the way I want it to.

    Thank you for all the help :)


    Please Mark as Answered If this answers your question Or UnMark as Answered if it did not.
    Happy to Help :)
    My Site

    Tuesday, May 27, 2014 8:43 AM

All replies

  • I don't know if I understand your question here but I you want to have a border around the ListBox, you could set its BorderBrush and BorderThickness properties in another converter class or even in the same converter class if you use a multibinding:

    <ListBox x:Name="lb" BorderBrush="Black" BorderThickness="0">
       <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
         <Canvas>
          <Canvas.Style>
           <Style TargetType="Canvas">
             <Style.Triggers>
              <DataTrigger Binding="{Binding Path= GRIDONOFF}" Value="True">
              <Setter Property="Background">
               <Setter.Value>
                <MultiBinding Converter="{StaticResource multiConverter}">
                 <Binding Path="Value" ElementName="mySlider"/>
                 <Binding Path="." ElementName="lb"/>
                </MultiBinding>
               </Setter.Value>
              </Setter>
              </DataTrigger>
             </Style.Triggers>
           </Style>
          </Canvas.Style>
         </Canvas>
        </ItemsPanelTemplate>
       </ListBox.ItemsPanel>
      </ListBox>

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
      {
       if (values[0] is double)
       {
        var GridSize = (double)values[0];
    
    
        var rect = new Rectangle
        {
         Width = GridSize,
         Height = GridSize,
         Stroke = new SolidColorBrush(Colors.DarkGray),
         StrokeThickness = 0.5,
         StrokeDashArray = new DoubleCollection { 1, GridSize * 4 },
         Fill =
          (SolidColorBrush)((new BrushConverter().ConvertFrom("#FF323337"))),
         SnapsToDevicePixels = true
        };
    
        //Construct the VisualBrush
        var brush = new VisualBrush
        {
         Viewbox = new Rect(0, 0, GridSize, layoutGridSize),
         Viewport = new Rect(0, 0, GridSize, GridSize),
         TileMode = TileMode.Tile,
         ViewboxUnits = BrushMappingMode.Absolute,
         ViewportUnits = BrushMappingMode.Absolute,
         Visual = rect
        };
    
        ListBox lb = values[1] as ListBox;
        lb.BorderThickness = new System.Windows.Thickness(10);
    
        return brush;
       }
      }
    


    Monday, May 26, 2014 1:05 PM
  • Thank you for the reply.

    Let me clarify,

    I want to have border for the canvas.

    That canvas is inside a listbox as show above. I have this converter class which gives me a grid as the canvas background. But I also want the canvas to have a border.


    Please Mark as Answered If this answers your question Or UnMark as Answered if it did not.
    Happy to Help :)
    My Site

    Tuesday, May 27, 2014 2:36 AM
  • Thank you for the reply.

    Let me clarify,

    I want to have border for the canvas.

    That canvas is inside a listbox as show above. I have this converter class which gives me a grid as the canvas background. But I also want the canvas to have a border.


    Please Mark as Answered If this answers your question Or UnMark as Answered if it did not.
    Happy to Help :)
    My Site


    Hi,

    AFAIK, there is no way to create a canvas with border in this case, Magnus's reply is a workaround, we can also find some ideas by using Snoop:

    In the above VisualTree, we can see the Canvas is the child node of a ScrollViewer and this ScrollViewer is also the child node of a Border.

    So we can change the Border's BorderThickness property from code behind(Window Loaded event):

    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
    {
                if (depObj != null)
                {
                    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                    {
                        DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                        if (child != null && child is T)
                        {
                            yield return (T)child;
                        }
    
                        foreach (T childOfChild in FindVisualChildren<T>(child))
                        {
                            yield return childOfChild;
                        }
                    }
                }
    }
    
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
                foreach (Border bd in FindVisualChildren<Border>(lb))
                {
                    bd.BorderBrush = Brushes.Black;
                    bd.BorderThickness = new System.Windows.Thickness(5);
                }
    }

    Screenshot:


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, May 27, 2014 6:45 AM
  • Thank you for the support.

    I did it this way after some searching around on the internet:

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                if (values[0] is double)
                {
                    var GridSize = (double)values[0];
                    SolidColorBrush girdColor = DarkGray
                    
                   
                    var rect = new Rectangle
                    {
                        Width = GridSize ,
                        Height = GridSize ,
                        Stroke = girdColor,
                        StrokeThickness = 0.5,
                        StrokeDashArray = new DoubleCollection { 1, GridSize * 4 },
                        Fill =
                            (SolidColorBrush)((new BrushConverter().ConvertFrom("DarkGray")),
                        SnapsToDevicePixels = true
                    };
    
                    
                    var brush = new VisualBrush
                    {
                        Viewbox = new Rect(0, 0, GridSize , GridSize ),
                        Viewport = new Rect(0, 0, GridSize , GridSize ),
                        TileMode = TileMode.Tile,
                        ViewboxUnits = BrushMappingMode.Absolute,
                        ViewportUnits = BrushMappingMode.Absolute,
                        Visual = rect
                    };
    
                    
                    Size bounds = new Size(Math.Floor((double)values[1]) -1, Math.Floor((double)values[2]) -1);
                    var outerGrid = new DrawingBrush
                    {
                        Stretch = Stretch.None,
                        AlignmentX = AlignmentX.Left,
                        AlignmentY = AlignmentY.Top,
                        Drawing = new GeometryDrawing
                        {
                            Geometry = new RectangleGeometry(new Rect(bounds)),
                            Pen = new Pen(girdColor, Constants.LAYOUT_GRID_STROKE_THICKNESS),
                            Brush = brush
                        }
                    };
    
                    return outerGrid;
                }
    
                return null;
            }

    I added an outer rectangle with Canvas height and width as its bounds and internal brush as my previous grid brush.

    This works the way I want it to.

    Thank you for all the help :)


    Please Mark as Answered If this answers your question Or UnMark as Answered if it did not.
    Happy to Help :)
    My Site

    Tuesday, May 27, 2014 8:43 AM