Extra binding stuff
This commit is contained in:
Родитель
01abb89295
Коммит
5ef1b8040c
|
@ -48,16 +48,48 @@ public static class ControlPropertyExtensions
|
|||
|
||||
return control;
|
||||
}
|
||||
|
||||
public static TControl _setCommonEx<TControl>(this TControl control, string sourcePropertyPathString, Action setAction,
|
||||
BindingMode? bindingMode, IValueConverter converter, object bindingSource)
|
||||
where TControl : AvaloniaObject
|
||||
{
|
||||
setAction();
|
||||
if (control is IDeclarativeViewBase viewBase)
|
||||
if (control is IDeclarativeViewBase viewBase)
|
||||
viewBase.UpdateState();
|
||||
return control;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Userd by autogenerated extensions from source generator for binding Common properties to ViewBase components
|
||||
/// </summary>
|
||||
/// <typeparam name="TControl"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
/// <param name="control"></param>
|
||||
/// <param name="setAction"></param>
|
||||
/// <param name="binding"></param>
|
||||
/// <returns></returns>
|
||||
public static TControl _setCommonBindingEx<TControl, TValue>(this TControl control, Action<TValue> setAction, IBinding ibinding)
|
||||
where TControl : AvaloniaObject
|
||||
{
|
||||
if (ibinding is ViewBase.BindingEx bindingEx)
|
||||
{
|
||||
TValue val = (TValue)bindingEx.Value;
|
||||
setAction(val);
|
||||
|
||||
if (control is ViewBase targetView)
|
||||
{
|
||||
targetView.UpdateState();
|
||||
|
||||
if (bindingEx.Source is ViewBase sourceView)
|
||||
{
|
||||
targetView.AddExternalState(sourceView, bindingEx.Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return control;
|
||||
}
|
||||
|
||||
public static TElement DataContext<TElement>(
|
||||
this TElement control,
|
||||
object value,
|
||||
|
|
|
@ -201,15 +201,23 @@ public abstract class ViewBase : Decorator, IReloadable, INotifyPropertyChanged,
|
|||
}
|
||||
|
||||
|
||||
|
||||
#region Property States
|
||||
|
||||
|
||||
ViewPropertyState[]? _propertyStates = null;
|
||||
List<ViewPropertyState> _externalPropertyStates = null;
|
||||
private void InitStateMembers()
|
||||
{
|
||||
var viewType = GetType();
|
||||
_propertyStates = viewType
|
||||
var viewPropertyStates = viewType
|
||||
.GetProperties()
|
||||
.Where(p => p.DeclaringType == viewType)
|
||||
.Select(p => new ViewPropertyState(p, this))
|
||||
.ToArray();
|
||||
.Select(p => new ViewPropertyState(p, this));
|
||||
|
||||
_propertyStates = _externalPropertyStates == null
|
||||
? viewPropertyStates.ToArray()
|
||||
: viewPropertyStates.Concat(_externalPropertyStates).ToArray();
|
||||
}
|
||||
public void UpdateState()
|
||||
{
|
||||
|
@ -226,6 +234,16 @@ public abstract class ViewBase : Decorator, IReloadable, INotifyPropertyChanged,
|
|||
OnPropertyChanged(prop.Name);
|
||||
}
|
||||
|
||||
public void AddExternalState<TContorl>(TContorl source, string propertyName)
|
||||
where TContorl : ViewBase
|
||||
{
|
||||
_externalPropertyStates ??= new List<ViewPropertyState>();
|
||||
|
||||
var propInfo = source.GetType().GetProperty(propertyName);
|
||||
|
||||
_externalPropertyStates.Add(new ViewPropertyState(propInfo, source));
|
||||
}
|
||||
|
||||
protected IBinding Bind(object value, BindingMode bindingMode = BindingMode.Default, [CallerArgumentExpression("value")] string bindingString = null)
|
||||
{
|
||||
object bindingSource = this;
|
||||
|
@ -251,14 +269,20 @@ public abstract class ViewBase : Decorator, IReloadable, INotifyPropertyChanged,
|
|||
if(useStateValueAsSource)
|
||||
bindingSource = stateInfo.Value;
|
||||
|
||||
return new Binding()
|
||||
return new BindingEx()
|
||||
{
|
||||
Source = bindingSource,
|
||||
Path = propName,
|
||||
Mode = bindingMode,
|
||||
Value = value
|
||||
};
|
||||
}
|
||||
|
||||
public class BindingEx : Binding
|
||||
{
|
||||
public object Value { get; set; }
|
||||
}
|
||||
|
||||
private ViewPropertyState FindStateForBindingString(string stateName) =>
|
||||
_propertyStates?.FirstOrDefault(x => x.Name == stateName);
|
||||
|
||||
|
@ -267,6 +291,7 @@ public abstract class ViewBase : Decorator, IReloadable, INotifyPropertyChanged,
|
|||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Hot reload stuff
|
||||
|
||||
|
|
|
@ -78,12 +78,13 @@ public class AvaloniaPropertyExtensionsGenerator : ISourceGenerator
|
|||
&& HasPublicSetter(property)
|
||||
&& IsCommonProperty(property, members))
|
||||
{
|
||||
var extensionString = GetCommonPropertySetterExtension(typeName, property);
|
||||
if (!string.IsNullOrWhiteSpace(extensionString))
|
||||
{
|
||||
//extensions.Add(extensionString);
|
||||
sb.AppendLine(extensionString);
|
||||
}
|
||||
var valueSetterExtensionString = GetCommonPropertySetterExtension(typeName, property);
|
||||
if (!string.IsNullOrWhiteSpace(valueSetterExtensionString))
|
||||
sb.AppendLine(valueSetterExtensionString);
|
||||
|
||||
var bindingSetterExtensionString = GetCommonPropertyBindingSetterExtension(typeName, property);
|
||||
if (!string.IsNullOrWhiteSpace(bindingSetterExtensionString))
|
||||
sb.AppendLine(bindingSetterExtensionString);
|
||||
}
|
||||
|
||||
//PROCESS AVALONIA PROPERTIES
|
||||
|
@ -213,16 +214,12 @@ public class AvaloniaPropertyExtensionsGenerator : ISourceGenerator
|
|||
private string GetCommonPropertyBindingSetterExtension(string controlTypeName, PropertyDeclarationSyntax property)
|
||||
{
|
||||
var extensionName = property.Identifier.ToString();
|
||||
|
||||
var valueTypeSource = property.Type.ToString();
|
||||
|
||||
var argsString = $"{valueTypeSource} value, BindingMode? bindingMode = null, IValueConverter converter = null, object bindingSource = null,"
|
||||
+ $" [CallerArgumentExpression(\"value\")] string ps = null";
|
||||
|
||||
var extensionText =
|
||||
$"public static {controlTypeName} {extensionName}"
|
||||
+ $"(this {controlTypeName} control, {argsString})"
|
||||
+ $"=> control._setCommonEx(ps, () => control.{extensionName} = value, bindingMode, converter, bindingSource);";
|
||||
+ $"(this {controlTypeName} control, IBinding binding)"
|
||||
+ $"=> control._setCommonBindingEx(({valueTypeSource} value) => control.{extensionName} = value, binding);";
|
||||
|
||||
return extensionText;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
namespace AvaloniaMarkupSample.MvuSample;
|
||||
using Avalonia.Markup.Declarative;
|
||||
|
||||
namespace AvaloniaMarkupSample.MvuSample;
|
||||
|
||||
public class MvuSampleView : ViewBase
|
||||
{
|
||||
|
@ -23,9 +25,10 @@ public class MvuSampleView : ViewBase
|
|||
.Background(Colors.Aquamarine.ToBrush())
|
||||
.Child(
|
||||
new MvuComponent()
|
||||
.Ref(out _nestedComponent)
|
||||
.ComponentParameter(Bind(MvuComponentParam))
|
||||
),
|
||||
|
||||
|
||||
new Button()
|
||||
.Content("Change nested component parameter")
|
||||
.OnClick(OnButton3Click)
|
||||
|
@ -33,6 +36,8 @@ public class MvuSampleView : ViewBase
|
|||
);
|
||||
|
||||
private string _myNotifiedProperty1 = "Click me";
|
||||
private MvuComponent _nestedComponent;
|
||||
|
||||
public string MyNotifiedProperty
|
||||
{
|
||||
get => _myNotifiedProperty1;
|
||||
|
@ -66,8 +71,7 @@ public class MvuSampleView : ViewBase
|
|||
|
||||
private void OnButton3Click(RoutedEventArgs obj)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
MvuComponentParam = "I changed from external view!";
|
||||
_nestedComponent.UpdateState();
|
||||
}
|
||||
|
||||
|
||||
}
|
Загрузка…
Ссылка в новой задаче