Entry コントロールの添付プロパティを、ContentView であるルート親のプロパティにバインドしようとしています。
(主に、NumBehaviors クラスで呼び出されたビューの ViewModel(BindingContext) を使用/アクセスするため)
デバッグで問題が明確に特定されないまま、アプリケーションが起動する前にクラッシュします:
オブジェクトの現在の状態のため、操作は無効です。
D:\a\1\s\Xamarin.Forms.Core\ Binding.cs:153 の Xamarin.Forms.Binding.ApplyRelativeSourceBinding (Xamarin.Forms.BindableObject targetObject, Xamarin.Forms.BindableProperty targetProperty) [0x00041] で
[エラー] 致命的な未処理例外: System.InvalidOperationException: オブジェクトの現在の状態のため、操作は無効です。
1- 何か間違ったことをしているのでしょうか (おそらくバインディングコンテキスト)?それとも、Xamarin はまだ wpf ほど適切にバインディングを処理していないのでしょうか (ElementName がないなど)?
2- デバッグ エラー/例外がそれほど明確ではないのはなぜですか?
MainView.xaml:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:Helpers="clr-namespace:App.Helpers"
xmlns:Behaviors="clr-namespace:App.Behaviors"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center"
x:Class="App.Views.MainView">
<Entry>
<Entry.Behaviors>
<Behaviors:NumBehaviors Helpers:HelperClass.Vm=
"{Binding Source={RelativeSource AncestorType={x:Type ContentView}}, Path=VM}"/>
</Entry.Behaviors>
</Entry>
HelperClass.cs
public static BindableProperty VmProperty =
BindableProperty.Create("Vm", typeof(object), typeof(HelperClass), null);
public static object GetVm(BindableObject bindable)
{
return (object)bindable.GetValue(VmProperty);
}
public static void SetVm(BindableObject bindable, object value)
{
bindable.SetValue(VmProperty, value);
}
MainView.cs
public object VM {get; set;}
public MainView()
{
InitializeComponent();
VM = (object) new MyViewModel();
BindingContext = VM;
}
NumBehaviors.cs
...
void OnEntryTextChanged(object sender, TextChangedEventArgs args) {
var usedvm = HelperClass.GetVm((BindableObject)sender);
}
次のコードを使用することもできますが、これは悪い考えだと思います。Entry の BindingContext がそのルート親の BindingContext と異なる場合、また柔軟性がない場合には役に立ちません。
...
void OnEntryTextChanged(object sender, TextChangedEventArgs args) {
var usedvm = ((Entry)sender).BindingContext;
}
追記:
私のアプローチが良くないのかもしれませんが、それを達成するためのより良いアプローチを受け入れるつもりです。
編集
Xamarin.Forms 4.8.0.1364 の使用
AncestorType={x:Type ContentView}} の代わりに AncestorType={x:Type local:MainView}} を使用しても同じ結果が得られました。
おそらくそれはこのオペに関連していますXamarin.Forms の未解決の問題 [バグ] AncestorType #9839 を使用するとコンパイルされたバインディングが機能しない
提供された Github のリンクから詳細を確認できます。
– ウェンディ ザン - MSFT
2020 年 9 月 7 日 9:49
1
関連: forums.xamarin.com/Discussion/183883/…
– クレイ・ブルックス
2020 年 9 月 11 日 17:41
@ClayBrooks 動作しています。受け入れられるように回答として入力していただけますか。また、間違いを犯したと思います。 Helpers:HelperClass.Vm.. は、Entry ではなく <Entry.. の添付プロパティである必要があります。 .Behaviors:NumBehaviors それ以外の場合は HelperClass.GetVm((BindableObject)sender);何らかの方法で送信者 (=Entry) の代わりにパラメータとして Sender.Behaviors:NumBehaviors を指定しない限り、常に null を返します。
– Cfun
2020 年 9 月 11 日 19:19
------------------------
RelativeSource はその祖先のバインディング コンテキストを見つけることができますが、動作は現在のビジュアル ツリーにありません。
バインディング コンテキストを示すためにこれを使用することをお勧めします。
Command="{Binding BindingContext.YourCommand, Source={x:Reference PageName}}"
YourCommand は BindingContext からアクセスできる必要があり、PageName は、<ContentPage ... x:Name="PageName" のように、それを囲む ContentPage の属性に設定する必要があります。
詳細については、こちらをご覧ください。最初の解決策を提供したそのリンクの男性に感謝します。
1
ユーザーが混乱しないように、質問の例のコンテキストに対する有効な回答にソリューションを適応させていただけますか?そして最も重要なのは、この場合 GetVm() のパラメータ オブジェクトが何になるかです。
– Cfun
2020 年 9 月 12 日 9:32
------------------------
この問題を回避するもう 1 つの解決策は、Attached プロパティを <Entry.Behaviors:NumBehaviors> から移動してデザインを変更することです。 <エントリ> へ:
<Entry Helpers:HelperClass.Vm="{Binding Source={RelativeSource AncestorType={x:Type ContentView}},
Path=VM}">
<Entry.Behaviors>
<Behaviors:NumBehaviors/>
</Entry.Behaviors>
</Entry>
この変更により、質問コードでプロパティ Vm をオブジェクト <Entry.Be に付加していた間違いも修正されます。動作:NumBehaviors>オブジェクト Sender(=Entry) (var usedvm = HelperClass.GetVm((BindableObject)sender);) から取得しようとしましたが、常に null を返します。
1
あなたがご自身で問題を解決し、その解決策を私たちに共有してくださったことを嬉しく思います。回答として受け入れていただければ、同様の問題を抱えている他のコミュニティにとって有益です。
– 呉張龍 - MSFT
2020 年 9 月 14 日 3:18