2

I'm currently trying to design a "stats" window that are known to be seen in RPG games, for example, showing how many points are distributed to Attack, Defense and Life.

For example, I have the Property Life in my Class, and in my XAML I have a WrapPanelwhere I want to host all these Rectangles that are going to represent each point the Property Life has, if that Property had the value "5", then 5 Rectangles would show up inside that WrapPanel.

Is it possible to do that purely in XAML with DataBinding without resorting to writing code? If purely doing that is not possible, is it possible doing it by writing a converter?

If one of those is possible, how?

I'm trying to make it mostly with Binding without writing code in the backend, to keep the code as less bloated and simple as possible.

EDIT: To clarify, 5 is not the maximum value, it can go as high as the datatype can go, so you have to consider that those Rectangles do have to dynamically be inserted with Binding instead of just inserting them and change the Visibility.

Steven Borges
  • 401
  • 1
  • 3
  • 16
  • Why the downvote? Instead of doing it for the heck of it, why not giving feedback so that I could improve the question if the content is not satisfactory? – Steven Borges Jun 22 '17 at 19:04
  • Add 5 rectangles, bind their visibility to the stat value, and use `ValueConverter` on the binding to make it visible if the value is greater to or equal to the value for that box. – Bradley Uffner Jun 22 '17 at 19:08
  • You do realize that wouldn't work if those stats go over 5, right? That's why it's in a WrapPanel to begin with, to automatically position it horizontally and vertically depending on how many are there... – Steven Borges Jun 22 '17 at 19:09
  • Ahh, I thought 5 was your max value. – Bradley Uffner Jun 22 '17 at 19:09
  • 3
    Create a public readonly property that returns `Enumerable.Range(1,X)` where X is your current stat value. Bind an `ItemsControl` to this. I think that will work for you. – Bradley Uffner Jun 22 '17 at 19:14
  • 3
    You could also write an `IValueConverter` that converts an integer directly to `Enumerable.Range(1,X)`. That converter would eliminate the extra property on the viewmodel, and makes the update notifications easier. – Bradley Uffner Jun 22 '17 at 19:17

1 Answers1

4

First write a converter which produces array of items from given number:

public class NumberToItemsConverter : IValueConverter {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        return Enumerable.Range(1, System.Convert.ToInt32(value));
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        throw new NotImplementedException();
    }
}

Then use items control:

<ItemsControl ItemsSource="{Binding Value, Converter={StaticResource numToItems}}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel IsItemsHost="True" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Rectangle Height="100"
                       Width="20"
                       Margin="5,0,5,0"
                       Fill="Red" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
Evk
  • 98,527
  • 8
  • 141
  • 191
  • `IsItemsHost` is new to me, the documentation on MSDN doesn't really explain why it's needed either, can you elaborate on that part? – Bradley Uffner Jun 22 '17 at 19:24
  • [This bridged the gap for me](https://stackoverflow.com/questions/2859656/what-exactly-does-panel-isitemshost-do). Thanks for showing me something new. – Bradley Uffner Jun 22 '17 at 19:26
  • @BradleyUffner well in this case it is not needed (though makes no harm either), I just use it because I used to do so. It is needed when you place panel in control template itself (like you found already). – Evk Jun 22 '17 at 19:26
  • Thanks I knew it was somewhere around this way, wasn't quite sure how. – Steven Borges Jun 22 '17 at 19:42