0

I'm trying to simply define the fill off all rectangle elements of the second stackpanel(of the two within the root stackpanel), the needed fill being white. Since a stackpanel doesn't have ItemTemplate I've tried replacing it with, and then encapsulating it with, ItemsControl. The encapsulation of the stack panel came to be when I saw that ItemsControl doesn't have an Orientation property.

Anyhow after all this the child rectangles still don't get filled with white... >.< what am I doing wrong?

(I also am trying to do same with the event bindings just like How to set an event function via a style? I'm still trying things out there, thought I wanted to do it via ItemControl as well initially, not working either tho atm :/ not my day)

<Window x:Class="RegenboogDragDrop.WindowRegenboog"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WindowRegenboog" Height="350" Width="525">
<Window.Resources>
    <Style TargetType="{x:Type Rectangle}">
        <Setter Property="Height" Value="50"></Setter>
        <Setter Property="Width" Value="50"></Setter>
        <Setter Property="Margin" Value="5"></Setter>
        <Setter Property="Stroke" Value="Black"></Setter>
        <Setter Property="StrokeThickness" Value="3"></Setter>
    </Style>

</Window.Resources>
    <StackPanel>
    <StackPanel Margin="0,50" Orientation="Horizontal" HorizontalAlignment="Center">
        <Rectangle Fill="Yellow" MouseMove="Rectangle_MouseMove"></Rectangle>
        <Rectangle Fill="Orange" MouseMove="Rectangle_MouseMove"></Rectangle>
        <Rectangle Fill="Red" MouseMove="Rectangle_MouseMove"></Rectangle>
        <Rectangle Fill="Blue" MouseMove="Rectangle_MouseMove"></Rectangle>
        <Rectangle Fill="Green" MouseMove="Rectangle_MouseMove"></Rectangle>
        <Rectangle Fill="Violet" MouseMove="Rectangle_MouseMove"></Rectangle>
        <Rectangle Fill="Indigo" MouseMove="Rectangle_MouseMove"></Rectangle>
    </StackPanel>
    <ItemsControl Name="DropZone" HorizontalAlignment="Center">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <Rectangle Fill="White"/>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>

        <StackPanel Orientation="Horizontal">
        <Rectangle Name="dropRed" Fill="White"/>
        <Rectangle Name="dropOrange" MouseMove="Rectangle_MouseMove" DragDrop.DragEnter="Rectangle_DragEnter" DragDrop.DragLeave="Rectangle_DragLeave" DragDrop.Drop="Rectangle_Drop" AllowDrop="True"></Rectangle>
        <Rectangle Name="dropYellow" Fill="White" MouseMove="Rectangle_MouseMove" DragDrop.DragEnter="Rectangle_DragEnter" DragDrop.DragLeave="Rectangle_DragLeave" DragDrop.Drop="Rectangle_Drop" AllowDrop="True"></Rectangle>
        <Rectangle Name="dropGreen"></Rectangle>
        <Rectangle Name="dropBlue"></Rectangle>
        <Rectangle Name="dropIndigo"></Rectangle>
        <Rectangle Name="dropViolet"></Rectangle>
        </StackPanel>
    </ItemsControl>
    <Button Name="ButtonCheck" Content="Check volgorde" Margin="5,50"></Button>
</StackPanel>

Code behind if you want to try it out: (On the second row the third square can receive colors by drag and drop, while the second has all the events but not the needed fill that I'm trying for it to have) (DutchVarsToEnglish: rechthoek means square, kleur means color, gesleepteKleur means draggedColor, sleep means drag):

https://defuse.ca/b/c19ncFwllWIpSRe6I0cclp (I can't figure out how to collapse a C# snippet just like the js snippet here https://meta.stackexchange.com/questions/70885/collapse-code-snippets-in-answers :S so pastebin link to codebehind)

Community
  • 1
  • 1
DeveloperDoge
  • 65
  • 1
  • 7

2 Answers2

3

Declare a default Rectangle Style in the Resources of the StackPanel:

<StackPanel>
    <StackPanel.Resources>
        <Style TargetType="Rectangle">
            <Setter Property="Fill" Value="White"/>
        </Style>
    </StackPanel.Resources>

    <Rectangle .../>
    ...
</StackPanel>

In case you have another default Rectangle Style higher in the element tree, you can base your "local default Style" on that Style be means of the Style's BasedOn property, like

<StackPanel.Resources>
    <Style TargetType="Rectangle" BasedOn="{StaticResource {x:Type Rectangle}}">
        <Setter Property="Fill" Value="White"/>
    </Style>
</StackPanel.Resources>
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • An elegant solution and you have an upvote from me as soon as I accept an answer(then I'll have 15 rep), however in this case I'm trying to learn how to do a thing (style child elements of stackpanel) so it'd be a hack for me. We could imagine there's a third row of boxes that need grey as filling (for, let's say, doing a reverse rainbow). I'd like to know how to do it without hacking(i.e. creating a special rectangle subtype or something in that range) – DeveloperDoge Feb 20 '17 at 12:13
  • Not sure what you mean by "hack". For styling child elements of a parent element, this is the way. Otherwise you would have to create Styles with an `x:Key` in some top-level resource dictionary, and explicitly assign them to the `Style` property of an element. – Clemens Feb 20 '17 at 12:21
  • aaaah yes I just saw what you meant, you're doing it in StackPanel.Resources ! How do I use BasedOn="..." here tho to get it to incorporate the above style. – DeveloperDoge Feb 20 '17 at 13:32
  • Ok figured it out `` can you add that to your answer I'll accept it then! – DeveloperDoge Feb 20 '17 at 13:54
1

You could define a class that has a Fill property:

public class Item
{
    public Brush Fill { get; set; }
}

And set the ItemsSource property of the ItemsControl to a collection of such objects:

public partial class WindowRegenboog : Window
{
    public WindowRegenboog()
    {
        InitializeComponent();
        DropZone.ItemsSource = new List<Item> { new Item { Fill = Brushes.Red }, new Item() { Fill = Brushes.Yellow } };
    }
}

You then bind the Fill property of the Rectangle in the ItemTemplate to the Fill source property:

<ItemsControl Name="DropZone" HorizontalAlignment="Center">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Rectangle Fill="{Binding Fill}" Width="200" Height="200"/>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

This way you could change the Fill colour of a Rectangle by simply setting the Fill property of an item in the source collection to a different brush.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • I appreciate the effort and clever binding +1. However I'll accept Clemens his best practice solution in the interest of others. I shouldn't have been dabbling with ItemTemplates, they don't work as expected in my case, complicate things and style even with it's visual studio bug on handler values, seems to be a more clear clean-cut approach. – DeveloperDoge Feb 21 '17 at 10:44
  • +1? You seem to have forgotten to vote. Anyway, using an implicit style won't work if you want to be able to control the fill of each of the Retangle elements separately. And using an ItemsControl with an ItemTemplate and data binding is best practice when you work with any kind of collection of items in XAML. – mm8 Feb 21 '17 at 10:48
  • Well right now my brain (exhausted from a lack of sleep), isn't able to fully comprehend why your approach would be better. As far as I understand you create a custom window class and somehow an item class with no base/inheriting/only one Property, then you do `DropZone.ItemsSource=new List {new Item{Fill=Brushes.Red }, new Item(){Fill=Brushes.Yellow}};` (colors could prob be made dynamic later), which I don't fully get. Which, in my humble experience makes me guess a big bit of other devs won't, forcing me to thread the perilous post nuclear apocalypse wastelands setting of non-KISS. – DeveloperDoge Feb 21 '17 at 13:03
  • (Ah yes, my apologies I must've gotten distracted or clicked before hitting 15. Fixed!) – DeveloperDoge Feb 21 '17 at 13:09