Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
CompositeInputView.cs
1using System.ComponentModel;
2using CommunityToolkit.Maui.Converters;
3using Microsoft.Maui.Controls.Shapes;
4using Path = Microsoft.Maui.Controls.Shapes.Path;
5using FormatedString = Microsoft.Maui.Controls.FormattedString;
6using Microsoft.Maui.Graphics.Text;
10{
11
12 public partial class CompositeInputView : ContentView
13 {
14
15 #region Fields
16 // UI Elements
17 protected Label label;
18 protected ContentView leftContentView;
19 protected ContentView centerContentView;
20 protected ContentView rightContentView;
21 protected Grid validationGrid;
22 protected Border border;
23
24 public bool CanShowValidation => !this.IsValid && !string.IsNullOrEmpty(this.ValidationText);
25 public bool CanShowLabel => !string.IsNullOrEmpty(this.LabelText);
26 #endregion
27
28 public CompositeInputView()
29 {
30 // Main Grid with 3 rows
31 Grid MainGrid = new Grid
32 {
33 RowDefinitions =
34 {
35 new RowDefinition { Height = GridLength.Auto }, // Label
36 new RowDefinition { Height = GridLength.Auto }, // Left, Center, Right Views
37 new RowDefinition { Height = GridLength.Auto } // Validation Icon and Text
38 }
39 };
40
41 MainGrid.RowSpacing = 2;
42
43 // Row 1: Single Label with FormattedText
44 this.label = new Label();
45 FormattedString Formatted = new FormattedString();
46
47 // Span for the main label text
48 Span LabelSpan = new Span();
49 LabelSpan.SetBinding(Span.TextProperty, new Binding(nameof(this.LabelText), source: this));
50
51 // Inherit styling from the owner label
52 LabelSpan.SetBinding(Span.TextColorProperty, new Binding(nameof(this.label.TextColor), source: this.label));
53 LabelSpan.SetBinding(Span.FontSizeProperty, new Binding(nameof(this.label.FontSize), source: this.label));
54 LabelSpan.SetBinding(Span.FontFamilyProperty, new Binding(nameof(this.label.FontFamily), source: this.label));
55 LabelSpan.SetBinding(Span.FontAttributesProperty, new Binding(nameof(this.label.FontAttributes), source: this.label));
56 LabelSpan.SetBinding(Span.TextDecorationsProperty, new Binding(nameof(this.label.TextDecorations), source: this.label));
57 LabelSpan.SetBinding(Span.CharacterSpacingProperty, new Binding(nameof(this.label.CharacterSpacing), source: this.label));
58 LabelSpan.SetBinding(Span.LineHeightProperty, new Binding(nameof(this.label.LineHeight), source: this.label));
59 LabelSpan.SetBinding(Span.TextTransformProperty, new Binding(nameof(this.label.TextTransform), source: this.label));
60 LabelSpan.SetBinding(Span.BackgroundColorProperty, new Binding(nameof(this.label.BackgroundColor), source: this.label));
61 LabelSpan.SetBinding(Span.FontAutoScalingEnabledProperty, new Binding(nameof(this.label.FontAutoScalingEnabled), source: this.label));
62
63 Formatted.Spans.Add(LabelSpan);
64
65 // Span for the required marker
66 Span RequiredMarkerSpan = new Span();
67 RequiredMarkerSpan.SetBinding(Span.TextProperty, new Binding(nameof(this.RequiredMarker), source: this));
68 RequiredMarkerSpan.Style = AppStyles.RequiredFieldMarkerSpan;
69 Formatted.Spans.Add(RequiredMarkerSpan);
70
71 this.label.FormattedText = Formatted;
72 this.label.SetBinding(Label.StyleProperty, new Binding(nameof(this.LabelStyle), source: this));
73 this.label.SetBinding(Label.IsVisibleProperty, new Binding(nameof(this.CanShowLabel), source: this));
74
75 MainGrid.Add(this.label, 0, 0);
76
77 // Row 2: LeftView, CenterView, RightView
78 Grid ContentGrid = new Grid
79 {
80 ColumnDefinitions =
81 {
82 new ColumnDefinition { Width = GridLength.Auto }, // LeftView
83 new ColumnDefinition { Width = GridLength.Star }, // CenterView
84 new ColumnDefinition { Width = GridLength.Auto } // RightView
85 },
86 ColumnSpacing = 0,
87 Margin = 0
88 };
89
90 // LeftView
91 this.leftContentView = new ContentView();
92 this.leftContentView.SetBinding(ContentView.ContentProperty, new Binding(nameof(this.LeftView), source: this));
93 ContentGrid.Add(this.leftContentView, 0, 0);
94
95 // CenterView
96 this.centerContentView = new ContentView();
97 this.centerContentView.SetBinding(ContentView.ContentProperty, new Binding(nameof(this.CenterView), source: this));
98 ContentGrid.Add(this.centerContentView, 1, 0);
99
100 // RightView
101 this.rightContentView = new ContentView();
102 this.rightContentView.SetBinding(ContentView.ContentProperty, new Binding(nameof(this.RightView), source: this));
103 ContentGrid.Add(this.rightContentView, 2, 0);
104
105 this.border = new Border()
106 {
107 Content = ContentGrid,
108 StrokeThickness = 0.5f,
109 HorizontalOptions = LayoutOptions.Fill,
110 Margin = 0
111 };
112 this.border.PropertyChanged += this.OnBorderPropertyChanged;
113 this.border.SetBinding(Border.StrokeProperty, new Binding(nameof(this.BorderStroke), source: this));
114 this.border.SetBinding(Border.StrokeShapeProperty, new Binding(nameof(this.BorderStrokeShape), source: this));
115 this.border.SetBinding(Border.BackgroundColorProperty, new Binding(nameof(this.BorderBackground), source: this));
116 this.border.SetBinding(Border.PaddingProperty, new Binding(nameof(this.BorderPadding), source: this));
117 MainGrid.Add(this.border, 0, 1);
118
119 // Row 3: ValidationIcon and ValidationText
120 this.validationGrid = new Grid
121 {
122 ColumnDefinitions =
123 {
124 new ColumnDefinition { Width = GridLength.Auto }, // ValidationIcon
125 new ColumnDefinition { Width = GridLength.Star } // ValidationText
126 }
127 };
128
129 // ValidationIcon
130 Path ValidationIcon = new();
131 ValidationIcon.SetBinding(Path.DataProperty, new Binding(nameof(this.ValidationIcon), source: this));
132 ValidationIcon.SetBinding(Path.FillProperty, new Binding(nameof(this.ValidationColor), source: this));
133 ValidationIcon.VerticalOptions = LayoutOptions.Center;
134 this.validationGrid.Add(ValidationIcon, 0, 0);
135 // ValidationText
136 Label ValidationLabel = new Label();
137 ValidationLabel.SetBinding(Label.TextProperty, new Binding(nameof(this.ValidationText), source: this));
138 ValidationLabel.SetBinding(Label.TextColorProperty, new Binding(nameof(this.ValidationColor), source: this));
139 ValidationLabel.SetBinding(Label.StyleProperty, new Binding(nameof(this.ValidationLabelStyle), source: this));
140 this.validationGrid.Add(ValidationLabel, 1, 0);
141
142 this.validationGrid.SetBinding(Grid.IsVisibleProperty, new Binding(nameof(this.CanShowValidation), source: this));
143
144 this.validationGrid.HorizontalOptions = LayoutOptions.Center;
145 this.validationGrid.Margin = AppStyles.SmallTopMargins;
146 this.validationGrid.ColumnSpacing = AppStyles.SmallSpacing;
147
148 MainGrid.Add(this.validationGrid, 0, 2);
149 // Set the Content of the ContentView to the MainGrid
150 this.Content = MainGrid;
151 }
152
153 #region Bindable Properties
154
155 public static readonly BindableProperty RequiredProperty =
156 BindableProperty.Create(
157 nameof(Required),
158 typeof(bool),
159 typeof(CompositeInputView),
160 false,
161 propertyChanged: OnRequiredChanged);
162
163 public bool Required
164 {
165 get => (bool)this.GetValue(RequiredProperty);
166 set => this.SetValue(RequiredProperty, value);
167 }
168
169 // LabelText Property
170 public static readonly BindableProperty LabelTextProperty =
171 BindableProperty.Create(nameof(LabelText), typeof(string), typeof(CompositeInputView), string.Empty, propertyChanged: OnLabelChanged);
172
173 public string LabelText
174 {
175 get => (string)this.GetValue(LabelTextProperty);
176 set => this.SetValue(LabelTextProperty, value);
177 }
178
179 // LeftView Property
180 public static readonly BindableProperty LeftViewProperty =
181 BindableProperty.Create(nameof(LeftView), typeof(View), typeof(CompositeInputView), null, propertyChanged: OnLeftViewChanged);
182
183 public View LeftView
184 {
185 get => (View)this.GetValue(LeftViewProperty);
186 set => this.SetValue(LeftViewProperty, value);
187 }
188
189 // CenterView Property
190 public static readonly BindableProperty CenterViewProperty =
191 BindableProperty.Create(nameof(CenterView), typeof(View), typeof(CompositeInputView), null);
192
193 public View CenterView
194 {
195 get => (View)this.GetValue(CenterViewProperty);
196 set => this.SetValue(CenterViewProperty, value);
197 }
198
199 // RightView Property
200 public static readonly BindableProperty RightViewProperty =
201 BindableProperty.Create(nameof(RightView), typeof(View), typeof(CompositeInputView), null, propertyChanged: OnRightViewChanged);
202
203 public View RightView
204 {
205 get => (View)this.GetValue(RightViewProperty);
206 set => this.SetValue(RightViewProperty, value);
207 }
208
209 // ValidationIcon Property
210 public static readonly BindableProperty ValidationIconProperty =
211 BindableProperty.Create(nameof(ValidationIcon), typeof(Geometry), typeof(CompositeInputView), Geometries.ErrorPath);
212
213 public Geometry ValidationIcon
214 {
215 get => (Geometry)this.GetValue(ValidationIconProperty);
216 set => this.SetValue(ValidationIconProperty, value);
217 }
218
219 // ValidationText Property
220 public static readonly BindableProperty ValidationTextProperty =
221 BindableProperty.Create(nameof(ValidationText), typeof(string), typeof(CompositeInputView), string.Empty, propertyChanged: OnValidationChanged);
222
223 public string ValidationText
224 {
225 get => (string)this.GetValue(ValidationTextProperty);
226 set => this.SetValue(ValidationTextProperty, value);
227 }
228
232 public static readonly BindableProperty ValidationLabelStyleProperty =
233 BindableProperty.Create(nameof(ValidationLabelStyle), typeof(Style), typeof(CompositeInputView));
234
239 {
240 get => (Style)this.GetValue(ValidationLabelStyleProperty);
241 set => this.SetValue(ValidationLabelStyleProperty, value);
242 }
243
247 public static readonly BindableProperty ValidationIconStyleProperty =
248 BindableProperty.Create(nameof(ValidationIconStyle), typeof(Style), typeof(CompositeInputView));
249
254 {
255 get => (Style)this.GetValue(ValidationIconStyleProperty);
256 set => this.SetValue(ValidationIconStyleProperty, value);
257 }
258
259 // IsValid Property
260 public static readonly BindableProperty IsValidProperty =
261 BindableProperty.Create(nameof(IsValid), typeof(bool), typeof(CompositeInputView), true, propertyChanged: OnValidationChanged);
262
263 public bool IsValid
264 {
265 get => (bool)this.GetValue(IsValidProperty);
266 set => this.SetValue(IsValidProperty, value);
267 }
268
272 public static readonly BindableProperty LabelStyleProperty =
273 BindableProperty.Create(nameof(LabelStyle), typeof(Style), typeof(CompositeInputView));
274
278 public Style LabelStyle
279 {
280 get => (Style)this.GetValue(LabelStyleProperty);
281 set => this.SetValue(LabelStyleProperty, value);
282 }
283
284 public static readonly BindableProperty ValidationColorProperty =
285 BindableProperty.Create(nameof(ValidationColor), typeof(Color), typeof(CompositeInputView), AppColors.ErrorBackground);
286
287 public Color ValidationColor
288 {
289 get => (Color)this.GetValue(ValidationColorProperty);
290 set => this.SetValue(ValidationColorProperty, value);
291 }
292 public string RequiredMarker => this.Required ? "*" : string.Empty;
293
294
295 #endregion
296
297 #region Border Bindable Properties
298
299 //Border Background Color
300 public static readonly BindableProperty BorderBackgroundProperty =
301 BindableProperty.Create(
302 nameof(BorderBackground),
303 typeof(Color),
304 typeof(CompositeInputView),
305 Colors.Transparent);
306 public Color BorderBackground { get => (Color)this.GetValue(BorderBackgroundProperty); set => this.SetValue(BorderBackgroundProperty, value); }
307
308 // Border Stroke Color
309 public static readonly BindableProperty BorderStrokeProperty =
310 BindableProperty.Create(
311 nameof(BorderStroke),
312 typeof(Color),
313 typeof(CompositeInputView),
314 Colors.Gray);
315
316 public Color BorderStroke
317 {
318 get => (Color)this.GetValue(BorderStrokeProperty);
319 set => this.SetValue(BorderStrokeProperty, value);
320 }
321
322 // Border Stroke Shape
323 public static readonly BindableProperty BorderStrokeShapeProperty =
324 BindableProperty.Create(
325 nameof(BorderStrokeShape),
326 typeof(Shape),
327 typeof(CompositeInputView),
328 new Rectangle());
329 public Shape BorderStrokeShape
330 {
331 get => (Shape)this.GetValue(BorderStrokeShapeProperty);
332 set => this.SetValue(BorderStrokeShapeProperty, value);
333 }
334
335 // Border Shadow
336 public static readonly BindableProperty BorderShadowProperty =
337 BindableProperty.Create(
338 nameof(BorderShadow),
339 typeof(Shadow),
340 typeof(CompositeInputView),
341 new Shadow());
342
343 public Shadow BorderShadow
344 {
345 get => (Shadow)this.GetValue(BorderShadowProperty);
346 set => this.SetValue(BorderShadowProperty, value);
347 }
348
349 // Border Padding
350 public static readonly BindableProperty BorderPaddingProperty =
351 BindableProperty.Create(
352 nameof(BorderPadding),
353 typeof(Thickness),
354 typeof(CompositeInputView),
355 new Thickness(0));
356
357 public Thickness BorderPadding
358 {
359 get => (Thickness)this.GetValue(BorderPaddingProperty);
360 set => this.SetValue(BorderPaddingProperty, value);
361 }
362
363 // Border Corner Radius
364 public static readonly BindableProperty BorderCornerRadiusProperty =
365 BindableProperty.Create(
366 nameof(BorderCornerRadius),
367 typeof(CornerRadius),
368 typeof(CompositeInputView),
369 new CornerRadius(5));
370
371 public CornerRadius BorderCornerRadius
372 {
373 get => (CornerRadius)this.GetValue(BorderCornerRadiusProperty);
374 set => this.SetValue(BorderCornerRadiusProperty, value);
375 }
376
377 #endregion
378
379 private static void OnRequiredChanged(BindableObject Bindable, object OldValue, object NewValue)
380 {
381 CompositeInputView Control = (CompositeInputView)Bindable;
382 Control.OnPropertyChanged(nameof(RequiredMarker));
383 }
384
385 private void OnBorderPropertyChanged(Object? Sender, PropertyChangedEventArgs E)
386 {
387
388 }
389
390 private static void OnValidationChanged(BindableObject Bindable, object OldValue, object NewValue)
391 {
392 CompositeInputView Control = (CompositeInputView)Bindable;
393
394 // Update CanShowValidation
395 Control.OnPropertyChanged(nameof(CanShowValidation));
396 // Nudge layout to ensure style triggers reflect immediately even if control isn't focused
397 Control.InvalidateMeasure();
398 }
399
400 private static void OnLabelChanged(BindableObject Bindable, object OldValue, object NewValue)
401 {
402 CompositeInputView Control = (CompositeInputView)Bindable;
403 Control.OnPropertyChanged(nameof(CanShowLabel));
404 }
405
406 private static void OnLeftViewChanged(BindableObject Bindable, object OldValue, object NewValue)
407 {
408 CompositeInputView Control = (CompositeInputView)Bindable;
409 bool HasLeft = NewValue is View;
410 // Apply spacing only when left view exists
411 Control.leftContentView.Margin = HasLeft ? new Thickness(0, 0, 8, 0) : new Thickness(0);
412 }
413
414 private static void OnRightViewChanged(BindableObject Bindable, object OldValue, object NewValue)
415 {
416 CompositeInputView Control = (CompositeInputView)Bindable;
417 bool HasRight = NewValue is View;
418 // Apply spacing only when right view exists
419 Control.rightContentView.Margin = HasRight ? new Thickness(8, 0, 0, 0) : new Thickness(0);
420 }
421 }
422}
Static class that gives access to app-specific themed colors. All colors are fetched directly from th...
Definition: AppColors.cs:8
static Color ErrorBackground
Error Background Color.
Definition: AppColors.cs:179
Static class that gives access to app-specific styles
Definition: AppStyles.cs:12
static Style RequiredFieldMarkerSpan
Style for required field marker spans
Definition: AppStyles.cs:421
static Thickness SmallTopMargins
Top-only small margins
Definition: AppStyles.cs:157
Style ValidationLabelStyle
Gets or sets the style applied to the validation label.
Style ValidationIconStyle
Gets or sets the style applied to the validation icon.
static readonly BindableProperty ValidationIconStyleProperty
Bindable property for the style applied to the validation icon.
static readonly BindableProperty LabelStyleProperty
Bindable property for the style applied to the label above the entry.
static readonly BindableProperty ValidationLabelStyleProperty
Bindable property for the style applied to the validation label.
Style LabelStyle
Gets or sets the style applied to the label above the entry.
Static class containing SVG Paths for symbols used in the app.
Definition: Geometries.cs:11