3

I have a collection of data items and am trying to use Fyne to put together a GUI to edit the collection. I've figured out how to use binding to display the collection, but I can't figure out how to then be able to edit the items.

Here's a slightly simplified version of what I have:

type Item struct {
  Name string
  Slot1 bool
  Slot2 bool
}

type ItemList struct {
  Items []Item
}

I won't show them, but I've added the methods to these two types so that the former implements binding.DataItem and the latter implements binding.DataList.

Now for the display:

var dataList := ItemList{
 ...
 ...
}

list := NewListWithData(
        dataList,
        func() fyne.CanvasObject {
           label := widget.NewLabel("placeholder")
           c1 := widget.NewCheck("", func(bool) {})
           c2 := widget.NewCheck("", func(bool) {})
           return container.NewHBox(label, c1, c2)
        },
        func(di binding.DatItem, obj fyne.CanvasObject) {
           ct := obj.(*fyne.Container)
           label := ct.Objects[0].(*widget.Label)
           c1 := ct.Objects[1].(*widget.Check)
           c2 := ct.Objects[2].(*widget.Check)
           item := di.(Item)
           label.SetText(item.Name)
           c1.SetChecked(item.Slot1)
           c2.SetChecked(item.Slot2)
        },
}

I suspect that at this point I need to do something like values := binding.BindStruct(&item), but if I do so, I'm not sure how to then get those into the label and check widgets.

Matthew Burke
  • 2,295
  • 17
  • 14
  • 1
    would love to see how you implemented those interfaces, it's so hard to get it from the source with no examples – vikkio Oct 05 '22 at 18:44

2 Answers2

1

You need to wire up the input controls to the binding (the item for the struct is passed in through di). If you already have the methods in Item that gain you access to the child items bound then you're most of the way there.

To wire up the edit capabilities replace label.SetText(...) with label.Bind(...) and c1.SetChecked(...) with c1.Bind(...). This will both set the current values an

andy.xyz
  • 2,567
  • 1
  • 13
  • 18
  • Thanks @andy.xyz, This is slowly getting more clear. I tried `c1.Bind(binding.BindBool(&mi.Slot1))` -- seems to be what you're suggesting. It compiles, but it doesn't change the underlying data structure. I've read the book "Building Cross-Platform GUI Applications with Fyne" and I think I understand the examples there, but they don't quite help me understand this more complicated situation. I've done a little Googling but couldn't turn up a better example. Are you aware of one you could point me to? – Matthew Burke May 01 '21 at 21:33
  • Almost - but you should use your DataItem (`di`) as your source (I can’t see what `mi` is so maybe that is what you meant). Perhaps if your `Item` implemented `DataMap` like the result of `BindStruct` would do then you can `label.Bind(di.(Item).Slot1Item()` (returning a data item instead of creating new bindings on the fly). – andy.xyz May 03 '21 at 07:26
  • When you bind values as you are doing it is critical that you are using a pointer to the original data source. Any intermediate variables will break the two-way-bind flow. – andy.xyz May 03 '21 at 07:26
0

I've read the book "Building Cross-Platform GUI Applications with Fyne" and I think I understand the examples there, but they don't quite help me understand this more complicated situation.

Hello, same here, read the book twice. I'm wanting to make a bind list of custom struct but the lack of exemples in the book and on the internet make the things very hard. Would be cool if someone can make an official tutorial on how to implement DataItem, DataList, DataStruct and wire it up with some widgets.

blaize
  • 119
  • 4