WPF - binding controls to array elements



  • I have a fixed-size array of enums in my ViewModel, and I want to bind each element to its own ComboBox. I'm not sure how to do it correctly. I tried:

    • Binding each to array property, and indexing in binding path. Except this way, only getter will get called, not setter.
    • Using ObservableCollection instead of plain array. Except I can't use indexing now, and I can't bind to expressions.
    • Making separate properties for each element. Except it leads to lots of code repetition. I thought of using T4 template, but after I saw all those security warning dialogs and lack of syntax highlighting, I started to doubt if T4 templates are a good (as in best practices) solution for anything at all.

    What should I do?



  • 75 views and 0 replies. Seriously, is there really nobody on this forum who ever used arrays in WPF?



  • @gąska said in WPF - binding controls to array elements:

    Seriously, is there really nobody on this forum who ever used arrays in WPF?

    Sorry, I wouldn't even know what WPF stands for without searching.


  • Impossible Mission - B

    @boomzilla Wildly Puzzling Framework. It's a new and "improved" .NET UI technology that replaced the perfectly adequate, stable, and easily-understood *ahem* badly outdated and soooo last decade WinForms with a big mess of XML so complicated it's been described as having a learning cliff rather than the usual learning curve.



  • @gąska I used to do WPF. I remember using ObservableCollections. Or maybe even I made my own collection that implements the change notification interface.

    But it's been years, I forgot all the details.

    Surely this shouldn't be a huge problem?



  • What'd you bind to? ItemsSource would normally work I would think... I'll go mess around with that.

    EDIT: Whoa, I see what you're trying to do now... I'm horrified, but I'll try it I guess...



  • I like WPF. I'll try.



  • Okay, so, if I'm reading you right, you want basically this?

    <ItemsControl ItemsSource="{Binding Whatevers}">
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <ComboBox ItemsSource="{Binding}"/>
        </DataTemplate>
      </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    The issue you'll face here, of course, is binding the selected item of each, since in this example we've just templated it. I'd probably make your array be of viewmodels that contain a property with the array and a property of the selected value.

    I like WPF a lot, but yeah, this is kind of an odd situation.

    I'll additionally note that there's a way to make the IDE recognize the type the datatemplate refers to and therefore allow completion to work and the properties to be recognized before runtime, but I don't remember how. It's been like a year since I've been able to actually work on WPF.



  • @masonwheeler said in WPF - binding controls to array elements:

    WinForms

    What are those? We like WTL here...



  • @dcon Windows forms are great for rapidly getting some UI up and running, though I think I know WPF thoroughly enough that the difference is minor for me. WPF, once you get what they're going for, can do amazing things really easily. I just wish they'd hook up the newer XAML version that has types and generics...



  • @magus I do know what they are 🙂 (even if I've never used them). The odds of moving to any of them are between slim and none.



  • @magus said in WPF - binding controls to array elements:

    once you get what they're going for

    My experience was "I've been waiting for exactly this" when I first saw WPF.
    Mind you, my previous GUI experience was Java Swing and Android, and all three in university courses.


  • Impossible Mission - B

    @marczellm I'm so sorry...


  • Winner of the 2016 Presidential Election

    @marczellm said in WPF - binding controls to array elements:

    @magus said in WPF - binding controls to array elements:

    once you get what they're going for

    My experience was "I've been waiting for exactly this" when I first saw WPF.
    Mind you, my previous GUI experience was Java Swing and Android, and all three in university courses.

    That revelation was followed shortly after by "Some of this stuff is way too needlessly complicated" in my case.



  • @magus said in WPF - binding controls to array elements:

    The issue you'll face here, of course, is binding the selected item of each, since in this example we've just templated it. I'd probably make your array be of viewmodels that contain a property with the array and a property of the selected value.

    So, if I understood properly, I should do something like:

    public class WindowVM: BindableBase // using Prism
    {
        public class ComboBoxVM: BindableBase
        {
            public static Foo[] ItemSource { get; } = ...;
            public Foo Selected { get; set; } = ...;
        }
        public ComboBoxVM[] ComboBoxVMs { get; }
    }
    

    And then bind individual ComboBoxes to these objects? How do I do it, exactly?

    Also. Converters are mostly single-use classes that are very lengthy to define. Is there some library of common converters, or is copy-pasting from StackOverflow the way to go? (I saw a lot of people copy-pasting RelayCommand and ViewModelBase around, then found Prism. Bug it doesn't have converters.)



  • @gąska That'd be an effective way to do it. You could probably do it all with anonymous types, except that the Selected property really needs to notify property changed. The binding ought to be like I showed above, except that in the combobox, you do <ComboBox ItemsSource="{Binding ItemsSource}" Selected="{Binding Selected}" ....

    Alternatively, if they all use the same options, you could bind them all to the same collection for that with different properties for each selected, or whatever else. It's pretty easy to deal with.

    As for converters, they're kind of a pain. I typically just define the ones I need. You can, if you want, define properties that you can set when defining a converter instance, and use those in the conversion in some way, but overall I'd tend more toward making them single-use and understandable. I don't know about libraries for them, but they really ought to exist.

    I personally do write my own DelegateCommand (similar to RelayCommand probably) in my own projects, and sometimes something like ViewModelBase, because I don't even need a quarter of Prism (I have a thread here about using MEF for lots of prismy things).

    As to the general case of binding combo boxes to collections like this, if you do it often you may want to make a style, and override the templates for both the items and the itemscontainer, but if this is a one-off, just go ahead and do it in place.



  • @magus said in WPF - binding controls to array elements:

    The binding ought to be like I showed above, except that in the combobox, you do <ComboBox ItemsSource="{Binding ItemsSource}" Selected="{Binding Selected}" ....

    I mean, where do I say in XAML that "no, don't bind these bindings to the window's viewmodel, but rather to your own little viewmodel that's a member of the main viewmodel that you can access via..."?

    @magus said in WPF - binding controls to array elements:

    I personally do write my own DelegateCommand (similar to RelayCommand probably) in my own projects, and sometimes something like ViewModelBase, because I don't even need a quarter of Prism (I have a thread here about using MEF for lots of prismy things).

    I'm also using it to bind events to commands (InvokeCommandAction). And I'm not rewriting this piece. So if I'm stuck with this dependency, let's use it.

    @magus said in WPF - binding controls to array elements:

    As to the general case of binding combo boxes to collections like this, if you do it often you may want to make a style, and override the templates for both the items and the itemscontainer, but if this is a one-off, just go ahead and do it in place.

    I don't use template, but I do use style. Not sure what's the difference between two (they seem to cover pretty much the same functionality), and I already know the syntax of the latter.



  • @magus is changing DataSource of child controls OK or will it open a can of worms similar to one I opened when I tried to add null to ComboBox's items?



  • @gąska said in WPF - binding controls to array elements:

    I mean, where do I say in XAML that "no, don't bind these bindings to the window's viewmodel, but rather to your own little viewmodel that's a member of the main viewmodel that you can access via..."?

    You don't have to. If you use an ItemsControl like I did above, each item's data bindings apply to their item in the ItemsSource collection bound to the control. It's automatic.

    @gąska said in WPF - binding controls to array elements:

    I don't use template, but I do use style. Not sure what's the difference between two (they seem to cover pretty much the same functionality), and I already know the syntax of the latter.

    A style lets you save specific values for properties and then apply that style to multiple things. The template of a control is what it actually visibly looks like: Any control can be completely overridden into anything you want with templates. Normally, messing with them too much is dangerous, because you risk your app looking weird, but an ItemsControl is essentially just there to be extended, and you can do all you need with one of those, just by applying an ItemTemplate with a style and maybe an ItemsContainerTemplate, if you want them to go horizontally or have spacing between them.



  • @magus said in WPF - binding controls to array elements:

    @gąska said in WPF - binding controls to array elements:

    I mean, where do I say in XAML that "no, don't bind these bindings to the window's viewmodel, but rather to your own little viewmodel that's a member of the main viewmodel that you can access via..."?

    You don't have to. If you use an ItemsControl like I did above, each item's data bindings apply to their item in the ItemsSource collection bound to the control. It's automatic.

    Oh, I see. Your ItemsControl repeatedly created ComboBox for each item in ItemsSource. That's not what I wanted.

    Anyway. I finally managed to make something that seems to work. I wonder how many conventions I broke with this code (I definitely broke Geneva Conventions).

            <Grid.Resources>
                <Style x:Key="wireComboBox" TargetType="ComboBox">
                    <Setter Property="Width" Value="70"/>
                    <Setter Property="Height" Value="Auto"/>
                    <Setter Property="Margin" Value="5"/>
                    <Setter Property="ItemsSource" Value="{Binding ColorsList}"/>
                    <Setter Property="SelectedValue" Value="{Binding Wire}"/>
                </Style>
            </Grid.Resources>
            <Label Grid.Row="0" Grid.Column="0" Margin="5" HorizontalAlignment="Center" Content="Wires:"/>
            <ComboBox Grid.Row="1" Grid.Column="0" Style="{StaticResource wireComboBox}" DataContext="{Binding Wires[0]}"/>
            <ComboBox Grid.Row="2" Grid.Column="0" Style="{StaticResource wireComboBox}" DataContext="{Binding Wires[1]}"/>
            <ComboBox Grid.Row="3" Grid.Column="0" Style="{StaticResource wireComboBox}" DataContext="{Binding Wires[2]}"/>
            <ComboBox Grid.Row="4" Grid.Column="0" Style="{StaticResource wireComboBox}" DataContext="{Binding Wires[3]}"/>
            <ComboBox Grid.Row="5" Grid.Column="0" Style="{StaticResource wireComboBox}" DataContext="{Binding Wires[4]}"/>
            <ComboBox Grid.Row="6" Grid.Column="0" Style="{StaticResource wireComboBox}" DataContext="{Binding Wires[5]}"/>
    

Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.