This commit is contained in:
Igor Gritsenko 2022-11-05 22:18:15 +03:00
Родитель 01abb89295
Коммит 5ef1b8040c
4 изменённых файлов: 80 добавлений и 22 удалений

Просмотреть файл

@ -48,6 +48,7 @@ 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
@ -58,6 +59,37 @@ public static class ControlPropertyExtensions
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,6 +25,7 @@ public class MvuSampleView : ViewBase
.Background(Colors.Aquamarine.ToBrush())
.Child(
new MvuComponent()
.Ref(out _nestedComponent)
.ComponentParameter(Bind(MvuComponentParam))
),
@ -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();
}
}