うDatabinding型安全なリファクタリング支援
-
19-09-2019 - |
質問
たいと思った時に結合する制御プロパティのオブジェクトになって提供プロパティの名前を文字列として返します。これは良くないので:
- の場合はプロパティは削除されますた に名称変更しないコンパイラ 警告が表示されます。
- が名前の変更の件 とリファクタリングツールで がデータを結合させ を更新しました。
- ないエラまで ランタイムの場合はタイプの物件 が間違っているのは、例えば結合する整数 日付の選択.
あるデザインパターンを取得する丸のこのものは、使いやすさデータの結合?
(この問題WinForm,Asp.net およびコンポーネントのラインナップおよびその他のシステム)
今見つかり"回避策のためのnameof()オペレーターのC#:typesafe databinding"これがまた良い出発点です。
都合に合った使用ポストプロセッサの後の編集コマンド notifypropertyweaver とします。
誰でも知ってのソリューションコンポーネントのラインナップのバインディングを行いXMLというよりもC#?
解決
コオリバーくんを始めようっていうソリューションの両方対応のリファクタリングタイプ。でも私の実施INotifyPropertyChangedで対応特性と改称。
での使用次のように記述されています。
checkBoxCanEdit.Bind(c => c.Checked, person, p => p.UserCanEdit);
textBoxName.BindEnabled(person, p => p.UserCanEdit);
checkBoxEmployed.BindEnabled(person, p => p.UserCanEdit);
trackBarAge.BindEnabled(person, p => p.UserCanEdit);
textBoxName.Bind(c => c.Text, person, d => d.Name);
checkBoxEmployed.Bind(c => c.Checked, person, d => d.Employed);
trackBarAge.Bind(c => c.Value, person, d => d.Age);
labelName.BindLabelText(person, p => p.Name);
labelEmployed.BindLabelText(person, p => p.Employed);
labelAge.BindLabelText(person, p => p.Age);
人のクラス方法を示し実施しINotifyPropertyChangedは、安全又は この答え のためのその他は実現にはINotifyPropertyChanged, ActiveSharp-自動INotifyPropertyChanged も良さそうに見える):
public class Person : INotifyPropertyChanged
{
private bool _employed;
public bool Employed
{
get { return _employed; }
set
{
_employed = value;
OnPropertyChanged(() => c.Employed);
}
}
// etc
private void OnPropertyChanged(Expression<Func<object>> property)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(BindingHelper.Name(property)));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
のサポートの結合のヘルパークラスではお肉になるので仕事:
namespace TypeSafeBinding
{
public static class BindingHelper
{
private static string GetMemberName(Expression expression)
{
// The nameof operator was implemented in C# 6.0 with .NET 4.6
// and VS2015 in July 2015.
// The following is still valid for C# < 6.0
switch (expression.NodeType)
{
case ExpressionType.MemberAccess:
var memberExpression = (MemberExpression) expression;
var supername = GetMemberName(memberExpression.Expression);
if (String.IsNullOrEmpty(supername)) return memberExpression.Member.Name;
return String.Concat(supername, '.', memberExpression.Member.Name);
case ExpressionType.Call:
var callExpression = (MethodCallExpression) expression;
return callExpression.Method.Name;
case ExpressionType.Convert:
var unaryExpression = (UnaryExpression) expression;
return GetMemberName(unaryExpression.Operand);
case ExpressionType.Parameter:
case ExpressionType.Constant: //Change
return String.Empty;
default:
throw new ArgumentException("The expression is not a member access or method call expression");
}
}
public static string Name<T, T2>(Expression<Func<T, T2>> expression)
{
return GetMemberName(expression.Body);
}
//NEW
public static string Name<T>(Expression<Func<T>> expression)
{
return GetMemberName(expression.Body);
}
public static void Bind<TC, TD, TP>(this TC control, Expression<Func<TC, TP>> controlProperty, TD dataSource, Expression<Func<TD, TP>> dataMember) where TC : Control
{
control.DataBindings.Add(Name(controlProperty), dataSource, Name(dataMember));
}
public static void BindLabelText<T>(this Label control, T dataObject, Expression<Func<T, object>> dataMember)
{
// as this is way one any type of property is ok
control.DataBindings.Add("Text", dataObject, Name(dataMember));
}
public static void BindEnabled<T>(this Control control, T dataObject, Expression<Func<T, bool>> dataMember)
{
control.Bind(c => c.Enabled, dataObject, dataMember);
}
}
}
この多くの新しいものクライアントまで、フルのC#3.5を示すだけで何が可能です。今ました 衛生的なマクロ lispプログラマーを停止電話にてお伺いしており二級市民)
他のヒント
のnameofオペレーターが実施されたクライアントまで、フルのC#6.0ます。純4.6VS2015月2015年までに以下の有効期限が切れていないことでC# < 6.0
な文字列を含有する物件の名称、長々と書きましたが、単純なクラスを表現樹木の名前を返し員:
using System;
using System.Linq.Expressions;
using System.Reflection;
public static class Member
{
private static string GetMemberName(Expression expression)
{
switch (expression.NodeType)
{
case ExpressionType.MemberAccess:
var memberExpression = (MemberExpression) expression;
var supername = GetMemberName(memberExpression.Expression);
if (String.IsNullOrEmpty(supername))
return memberExpression.Member.Name;
return String.Concat(supername, '.', memberExpression.Member.Name);
case ExpressionType.Call:
var callExpression = (MethodCallExpression) expression;
return callExpression.Method.Name;
case ExpressionType.Convert:
var unaryExpression = (UnaryExpression) expression;
return GetMemberName(unaryExpression.Operand);
case ExpressionType.Parameter:
return String.Empty;
default:
throw new ArgumentException("The expression is not a member access or method call expression");
}
}
public static string Name<T>(Expression<Func<T, object>> expression)
{
return GetMemberName(expression.Body);
}
public static string Name<T>(Expression<Action<T>> expression)
{
return GetMemberName(expression.Body);
}
}
このクラスとしております。もできるのみご利用いただきますようにコード(うなー)では、非常に少なくとも私にとって、コードはまだいないtypesafe.きのメソッド名と第二の型引数を定義し、返却値の型に"byte[]"を指定機能、制限の種類、料金はお返しできません。
var name = Member.Name<MyClass>(x => x.MyProperty); // name == "MyProperty"
今までいたものを解決するのdatabinding typesafetyます。
ベストについて
の枠組み4.5を提供してくれる CallerMemberNameAttribute
, は、の物件の名称を文字列として不要:
private string m_myProperty;
public string MyProperty
{
get { return m_myProperty; }
set
{
m_myProperty = value;
OnPropertyChanged();
}
}
private void OnPropertyChanged([CallerMemberName] string propertyName = "none passed")
{
// ... do stuff here ...
}
ばねの枠組み4.0 KB2468871 設置インストールすることができる Microsoft BCLパックの互換性 通 nuget, でもこの属性。
このブログ 記事を一つの性能をこのアプローチ.きの利便性向上のためにその欠点を変換することにより、表現文字列の一部としての静的初期化.
実際の力学が目障がいのテンプレートをお使いください-安全で、約と同じような原INotifyPropertyChanged.
うようになります:
public class DummyViewModel : ViewModelBase
{
private class DummyViewModelPropertyInfo
{
internal readonly string Dummy;
internal DummyViewModelPropertyInfo(DummyViewModel model)
{
Dummy = BindingHelper.Name(() => model.Dummy);
}
}
private static DummyViewModelPropertyInfo _propertyInfo;
private DummyViewModelPropertyInfo PropertyInfo
{
get { return _propertyInfo ?? (_propertyInfo = new DummyViewModelPropertyInfo(this)); }
}
private string _dummyProperty;
public string Dummy
{
get
{
return this._dummyProperty;
}
set
{
this._dummyProperty = value;
OnPropertyChanged(PropertyInfo.Dummy);
}
}
}
一方フィードバックを得ることが出来ればバインディングが壊れをDataTemplateことを宣言し、そのデータ型の種類のViewModelで結合する例またPersonView、PersonViewModelきは次のように処理されます:
を宣言しDataTemplateとDataType=PersonViewModelやキーなどPersonTemplate)
カPersonView ー貼り付け、データのテンプレートを理想的にするだけではPersonView.
3a.をContentControlのContentTemplate=PersonTemplateと結合するコンテンツのPersonViewModel.
3b.ノイズに悩まされることもありませんのDataTemplate、設定されていないContentTemplateのContentControl.この場合はコンポーネントのラインナップは何をDataTemplate利用で認知が広がってい型のオブジェクトで結合す。で検索出だDataTemplateでマッチの種類、結合、自動的に適用すのContentTemplate.
またほぼ同じに見てもらいマッピングDataTemplateを基本データ型、工具のように簡単に、ios、androidとmac用にc#できます(経由色の識別子-簡単に、ios、androidとmac用にc#-オプション設定のカラー識別子としてil自のバインディングが壊れています。
まもなくコンパイラの警告ができる視覚的にチェックのための折れたバインディングだけが上がるようになるでしょうが、チェック、およびviewmodel.
他の追加情報であることもできます使用する名前の変更refactorings.私が覚えてい簡単に、ios、androidとmac用にc#で自動的に名前の変更のバインディングに入力DataTemplatesることができたり、背後にあるViewModelのプロパティ名を変更します。
1.の場合はプロパティは削除されますまたは名前の変更を行いないコンパイラの警告が表示されます。
2.が名前の変更、鉄骨構造で新耐震基準のリファクタリングツール、そのデータとの結合は更新されません。
3.ったり下がったりよくわからないエラーでランタイムの場合はタイプの物件は間違っているのは、例えば結合整数の日付の選択.
あり、イアン-この題名の文字列駆動データに結合する。また、デザインパターンです。シンプルにデザインしてみましたの型保証ビューモデル(TVM)パターンであるconcretionビューのモデルのモデルビュー-ViewModel(ョ)パターンです。ニーズに対応することができ型-安心の結合には、同様にお答えです。いただきました、掲載して解コンポーネントのラインナップ:
http://www.codeproject.com/Articles/450688/Enhanced-MVVM-Design-w-Type-Safe-View-Models-TVM
x:bind("とも呼ばれるデータバインディング")のためのポ(ユニバーサルアプリ)でwindows10およびwindows phone10月はこうした問題を解決覧 https://channel9.msdn.com/Events/Build/2015/3-635
して行docsではないように、またしていきたいと思いません。しかしこの答えは有用なポインタ。