Xamarin.android MVxRadioGroup SelectedIndexBinding

Xamarin.android MVxRadioGroup SelectedIndexBinding,xamarin.android,mvvmcross,Xamarin.android,Mvvmcross,我从MvxRadioGroupSelectedItemBinding的源创建了一个RadioGroupSelectedIndexBinding public class MvxRadioGroupSelectedIndexBinding : MvxAndroidTargetBinding { bool stopListeningCheckChanged = false; private int selectedIndex = -2; public int Selecte

我从MvxRadioGroupSelectedItemBinding的源创建了一个RadioGroupSelectedIndexBinding

public class MvxRadioGroupSelectedIndexBinding : MvxAndroidTargetBinding
{
    bool stopListeningCheckChanged = false;

    private int selectedIndex = -2;
    public int SelectedIndex
    { 
        get { return selectedIndex; }
        set { if(value != selectedIndex) { selectedIndex = value; FireValueChanged(SelectedIndex); } }
    }

    public static void Register(IMvxTargetBindingFactoryRegistry registry)
    {
        registry.RegisterCustomBindingFactory<RadioGroup>("SelectedIndex", radioGroup => new MvxRadioGroupSelectedIndexBinding(radioGroup));
    }

    public MvxRadioGroupSelectedIndexBinding(RadioGroup radioGroup) : base(radioGroup)
    {
        if (radioGroup == null)
        {
            Mvx.Trace(MvxTraceLevel.Error, "RadioGroup SelectedIndex: radioGroup is null");
            return;
        }

        radioGroup.CheckedChange += CheckedChange;
        radioGroup.ChildViewAdded += RadioGroupOnChildViewAdded;
    }

    private void RadioGroupOnChildViewAdded(object sender, ViewGroup.ChildViewAddedEventArgs childViewAddedEventArgs)
    {
        var radioGroup = Target as RadioGroup;
        if (selectedIndex == radioGroup.ChildCount-1)
        {
            stopListeningCheckChanged = true;
            radioGroup.Check(radioGroup.GetChildAt(selectedIndex).Id);
            stopListeningCheckChanged = false;
        }
    }

    private void CheckedChange(object sender, RadioGroup.CheckedChangeEventArgs e)
    {
        if (stopListeningCheckChanged)
            return;

        var radioGroup = Target as RadioGroup;
        var checkedId = e.CheckedId;

        if (checkedId == View.NoId)
        {
            SelectedIndex = -1;
            return;
        }

        for (var i = radioGroup.ChildCount - 1; i >= 0; i--)
        {
            if (checkedId == radioGroup.GetChildAt(i).Id)
            {
                SelectedIndex = i;
                return;
            }
        }
        SelectedIndex = -1;
        Mvx.Trace(MvxTraceLevel.Error, "RadioGroup id not found: {0}", checkedId);
    }

    public override void SetValue(object index)
    {
        var radioGroup = Target as RadioGroup;
        if (radioGroup == null)
            return;

        stopListeningCheckChanged = true;
        selectedIndex = (int)index;
        if (selectedIndex < 0 || selectedIndex >= radioGroup.ChildCount)
        {
            radioGroup.ClearCheck();
        }
        else
        {
            radioGroup.Check(radioGroup.GetChildAt(selectedIndex).Id);
        }
        stopListeningCheckChanged = false;
    }

    public override Type TargetType
    {
        get { return typeof(object); }
    }

    protected override void SetValueImpl(object target, object value)
    {
    }

    public override MvxBindingMode DefaultMode
    {
        get { return MvxBindingMode.TwoWay; }
    }

    protected override void Dispose(bool isDisposing)
    {
        if (isDisposing)
        {
            var radioGroup = Target as RadioGroup;
            if (radioGroup != null)
            {
                radioGroup.CheckedChange -= CheckedChange;
                radioGroup.ChildViewAdded -= RadioGroupOnChildViewAdded;
            }
        }
        base.Dispose(isDisposing);
    }
}
它工作正常,但在viewmodel启动时不起作用:调用了从viewmodel到视图的绑定,但此时RadioGroup没有子视图。看起来他们还没有被充气

这是Mvvmcross定制充气机/绑定中的“错误”(或功能:p)?或者在MvxAndroidTargetBinding中有什么东西需要重载

编辑:MvxRadioGroupSelectedIndexBinding的代码(索引,而非项:不同于MvxRadioGroupSelectedItemBinding)

公共类MvxRadioGroupSelectedIndexBinding:MvxAndroidTargetBinding
{
bool stoplistingcheckchanged=false;
私有int selectedIndex=-2;
公共整数选择索引
{ 
获取{return selectedIndex;}
设置{if(value!=selectedIndex){selectedIndex=value;FireValueChanged(selectedIndex);}
}
公共静态无效寄存器(IMvxTargetBindingFactoryRegistry注册表)
{
registry.RegisterCustomBindingFactory(“SelectedIndex”,radioGroup=>new MVxRadioGroup SelectedIndexBinding(radioGroup));
}
公共MVX射线组SelectedIndexBinding(射线组射线组):基本(射线组)
{
如果(放射组==null)
{
跟踪(MvxTraceLevel.Error,“RadioGroup SelectedIndex:RadioGroup为空”);
返回;
}
radioGroup.CheckedChange+=CheckedChange;
radioGroup.ChildViewAdded+=RadioGroupOnChildViewEded;
}
private void RadioGroupOnChildViewed(对象发送者,ViewGroup.ChildViewAddedEventArgs ChildViewAddedEventArgs)
{
var radioGroup=目标为radioGroup;
如果(selectedIndex==radioGroup.ChildCount-1)
{
StopListengCheckChanged=true;
radioGroup.Check(radioGroup.GetChildAt(selectedIndex.Id));
StopListingCheckChanged=false;
}
}
私有void CheckedChange(对象发送方,RadioGroup.CheckedChangeEventArgs e)
{
如果(StopListingCheckChanged)
返回;
var radioGroup=目标为radioGroup;
var checkedId=e.checkedId;
if(checkedId==View.NoId)
{
SelectedIndex=-1;
返回;
}
对于(变量i=radioGroup.ChildCount-1;i>=0;i--)
{
if(checkedId==radioGroup.GetChildAt(i.Id)
{
SelectedIndex=i;
返回;
}
}
SelectedIndex=-1;
Trace(MvxTraceLevel.Error,“未找到放射组id:{0}”,checkedId);
}
公共覆盖无效集合值(对象索引)
{
var radioGroup=目标为radioGroup;
如果(放射组==null)
返回;
StopListengCheckChanged=true;
selectedIndex=(int)索引;
如果(selectedIndex<0 | | selectedIndex>=radioGroup.ChildCount)
{
radioGroup.ClearCheck();
}
其他的
{
radioGroup.Check(radioGroup.GetChildAt(selectedIndex.Id));
}
StopListingCheckChanged=false;
}
公共覆盖类型TargetType
{
获取{return typeof(object);}
}
受保护的覆盖无效SetValueImpl(对象目标,对象值)
{
}
公共覆盖MvxBindingMode默认模式
{
获取{return MvxBindingMode.TwoWay;}
}
受保护的覆盖无效处置(bool isDisposing)
{
if(isDisposing)
{
var radioGroup=目标为radioGroup;
如果(放射组!=null)
{
radioGroup.CheckedChange-=CheckedChange;
radioGroup.ChildViewAdded-=radioGroup ChildViewAdded;
}
}
基础处理(isDisposing);
}
}
用法

    <RadioGroup
        android:orientation="horizontal"
        local:MvxBind="SelectedIndex SelectedChoiceIndex">
        <RadioButton
            android:text="choice 1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <RadioButton
            android:text="choice 2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </RadioGroup>

“错误”是当调用SetValue时,RadioGroup没有子对象。我假设自定义充气器同时创建和绑定视图。事实上,只有当他们的孩子被夸大时,它才应该约束观点。我可能错了,我没有检查源代码。它还可能有其他不良副作用

这是Mvvmcross定制充气机/绑定中的“错误”(或功能:p)

两者都不是-我认为这完全超出了
MvxRadioGroup
的设计目标范围

MVxRadioGroup SelectedItemBinding
是一个用户贡献,我相信它的设计目的就是要完全按照如下所示使用:


=>因此,它设计用于首先设置
ItemsSource
的项目列表,然后再设置
SelectedItem

我不相信MvxRadioGroup的作者有任何支持基于AXML的无线电选择列表的意图


话虽如此,如果有人想编写更广泛的RadioGroup解决方案-例如,可以处理AXML定义的列表,或者可以处理
ItemsSource
设置
SelectedItem
后的更改,然后我认为这应该是完全可能做到的-看起来你已经朝着这个方向走了很长的路:)完美地处理所有动态和静态列表更改的组合,可能需要使用某种技术,每次添加
itemsource
和/或静态项时都会重新检查
SelectedItem
属性。出于实际原因,我认为这种重新检查需要在一些自定义的RadioGroup和/或基于绑定的代码中执行——我认为在XML膨胀处理程序中没有任何方法可以做到这一点,因为Android在膨胀期间根本不提供任何合适的
ChildrenInflated和Added
类型回调

值得注意的是,XAML在这方面也面临着类似的挑战,例如,有关XAML
组合框
场景,请参见,其中项目必须在所选项目之前设置。。

我发现了一个wo
<MvxRadioGroup
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:textSize="40dp"
  local:MvxItemTemplate="@layout/item_radio"
  local:MvxBind="ItemsSource Items;SelectedItem SelectedItem"
 />