Golang WalkでRadioButtonの選択をコードから変更する

Golang Walkでラジオボタンの選択をコードから変更する方法を試しました。

```
package main

import (
	"fmt"
)

import (
	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)

type Foo struct {
	Bar string
	Baz int
}

func main() {
	foo := &Foo{"b", 0}
	var db *walk.DataBinder
	var rbBar [3]*walk.RadioButton
	var rbBaz [3]*walk.RadioButton

	MainWindow{
		Title:   "Walk RadioButton Example",
		MinSize: Size{320, 240},
		Layout:  VBox{},
		DataBinder: DataBinder{
			AssignTo: &db,
			DataSource: foo,
			AutoSubmit: true,
			OnSubmitted: func() {
				fmt.Println(foo)
			},
		},
		Children: []Widget{
			// RadioButtonGroup is needed for data binding only.
			RadioButtonGroup{
				DataMember: "Bar",
				Buttons: []RadioButton{
					RadioButton{
						AssignTo: &rbBar[0],
						Name:  "aRB",
						Text:  "A",
						Value: "a",
					},
					RadioButton{
						AssignTo: &rbBar[1],
						Name:  "bRB",
						Text:  "B",
						Value: "b",
					},
					RadioButton{
						AssignTo: &rbBar[2],
						Name:  "cRB",
						Text:  "C",
						Value: "c",
					},
				},
			},
			Label{
				Text:    "A",
				Enabled: Bind("aRB.Checked"),
			},
			Label{
				Text:    "B",
				Enabled: Bind("bRB.Checked"),
			},
			Label{
				Text:    "C",
				Enabled: Bind("cRB.Checked"),
			},
			RadioButtonGroup{
				DataMember: "Baz",
				Buttons: []RadioButton{
					RadioButton{
						AssignTo: &rbBaz[0],
						Name:  "oneRB",
						Text:  "1",
						Value: 1,
					},
					RadioButton{
						AssignTo: &rbBaz[1],
						Name:  "twoRB",
						Text:  "2",
						Value: 2,
					},
					RadioButton{
						AssignTo: &rbBaz[2],
						Name:  "threeRB",
						Text:  "3",
						Value: 3,
					},
				},
			},
			Label{
				Text:    "1",
				Enabled: Bind("oneRB.Checked"),
			},
			Label{
				Text:    "2",
				Enabled: Bind("twoRB.Checked"),
			},
			Label{
				Text:    "3",
				Enabled: Bind("threeRB.Checked"),
			},
			PushButton{
				Text: "Apply from Code",
				OnClicked: func() {
					// ここに実装する
				},
			},
		},
	}.Run()
}
```
初期画面はこちら。
![20180429_walk radiobutton 1.jpg](https://qiita-image-store.s3.amazonaws.com/0/252253/cf6bcd7b-0fb7-fafd-e766-f770d0ffcc17.jpeg)

「Apply from Code」ボタンがクリックされたらfoo.Barを"c"、foo.Bazを3にセットし、ラジオボタンの選択を変更したいとします。
![20180429_walk radiobutton 2.jpg](https://qiita-image-store.s3.amazonaws.com/0/252253/283d43ee-f0ca-f763-7126-c1160e1e9038.jpeg)

まず、fooに値をセットします。

			PushButton{
				Text: "Apply from Code",
				OnClicked: func() {
					foo.Bar = "c"
					foo.Baz = 3
				},
			},

これでラジオボタンにも反映されれば言うことなしですが、反映してくれません。
自力でラジオボタンの選択状態を更新してみます。

**1. RadioButton.SetChecked(true)する方法**

			PushButton{
				Text: "Apply from Code",
				OnClicked: func() {
					foo.Bar = "c"
					foo.Baz = 3

					cbBar := rbBar[0].Group().CheckedButton()
					if cbBar != nil {
						cbBar.SetChecked(false)
					}
					for _, rb := range rbBar {
						if rb.Value() == foo.Bar {
							rb.SetChecked(true)
							break
						}
					}

					cbBaz := rbBaz[0].Group().CheckedButton()
					if cbBaz != nil {
						cbBaz.SetChecked(false)
					}
					for _, rb := range rbBaz {
						if rb.Value() == foo.Baz {
							rb.SetChecked(true)
							break
						}
					}
				},
			},
RadioButtonのSetCheckedを使いました。これ一見うまくいきそうですが、rb.Group().CheckButton()がSetCheckedしたrbに書き変わらないため、実行すると奇妙な現象が起きます（チェックをオフにしたはずのラジオボタンが再び選択状態になる）

**2. RadioButtonのCheckedValueプロパティを使用する方法**
ソースコードを眺めていたら、きちんとrb.Group().CheckButton()を書き換えてくれるプロパティがRadioButtonにありました。
CheckedValueというプロパティです。

```
   rb.MustRegisterProperty("CheckedValue", NewProperty(
        func() interface{} {
            if rb.Checked() {
                return rb.value
            }

            return nil
        },
        func(v interface{}) error {
            checked := v == rb.value
            if checked {
                rb.group.checkedButton = rb
            }
            rb.SetChecked(checked)

            return nil
        },
        rb.CheckedChanged()))
```
これを使うと期待通りの動作をします。

			PushButton{
				Text: "Apply from Code",
				OnClicked: func() {
					foo.Bar = "c"
					foo.Baz = 3
					cbBar := rbBar[0].Group().CheckedButton()
					if cbBar != nil {
						prop := cbBar.AsWindowBase().Property("CheckedValue")
						prop.Set(foo.Bar)
					}
					for _, rb := range rbBar {
						if rb.Value() == foo.Bar {
							prop := rb.AsWindowBase().Property("CheckedValue")
							prop.Set(foo.Bar)
							break
						}
					}

					cbBaz := rbBaz[0].Group().CheckedButton()
					if cbBaz != nil {
						prop := cbBaz.AsWindowBase().Property("CheckedValue")
						prop.Set(foo.Baz)
					}
					for _, rb := range rbBaz {
						if rb.Value() == foo.Baz {
							prop := rb.AsWindowBase().Property("CheckedValue")
							prop.Set(foo.Baz)
							break
						}
					}

**3. DataBinder.Reset()を使う方法**
DataBinderを使っているのだから、DataSourceをUIに反映する方法があるはずだと思ってソースコードを眺めていたら、DataBinderにReset()というメソッドがありました。
次のように実装します。

			PushButton{
				Text: "Apply from Code",
				OnClicked: func() {
					foo.Bar = "c"
					foo.Baz = 3
					
					db.Reset()
				},
			},

これも期待通りの動作をします。これが正解ですね多分。