In code behind this is done by
ActivityList.ScrollIntoView(ActivityList.SelectedItem);
when you come back from the detailpage so that when you return from the detailpage you don't have to start from the top of the ListView.
There are a few examples to scroll to the end of a ListView but not to the SelectedItem.
But how is this done in MVVM? Creating a Behavior with Behavior SDK? And how?
I've done this with an attached-property (behavior). This behavior is in a class called DataGridExtensions and looks like:
public static readonly DependencyProperty ScrollSelectionIntoViewProperty = DependencyProperty.RegisterAttached(
"ScrollSelectionIntoView", typeof(bool), typeof(DataGridExtensions), new PropertyMetadata(false, ScrollSelectionIntoViewChanged));
private static void ScrollSelectionIntoViewChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = d as DataGrid;
if (dataGrid == null)
return;
if (e.NewValue is bool && (bool)e.NewValue)
dataGrid.SelectionChanged += DataGridOnSelectionChanged;
else
dataGrid.SelectionChanged -= DataGridOnSelectionChanged;
}
private static void DataGridOnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems == null || e.AddedItems.Count == 0)
return;
DataGrid dataGrid = sender as DataGrid;
if (dataGrid == null)
return;
ScrollViewer scrollViewer = UIHelper.FindChildren<ScrollViewer>(dataGrid).FirstOrDefault();
if (scrollViewer != null)
{
dataGrid.ScrollIntoView(e.AddedItems[0]);
}
}
public static void SetScrollSelectionIntoView(DependencyObject element, bool value)
{
element.SetValue(ScrollSelectionIntoViewProperty, value);
}
public static bool GetScrollSelectionIntoView(DependencyObject element)
{
return (bool)element.GetValue(ScrollSelectionIntoViewProperty);
}
The code of UIHelper.FindChildren is:
public static IList<T> FindChildren<T>(DependencyObject element) where T : FrameworkElement
{
List<T> retval = new List<T>();
for (int counter = 0; counter < VisualTreeHelper.GetChildrenCount(element); counter++)
{
FrameworkElement toadd = VisualTreeHelper.GetChild(element, counter) as FrameworkElement;
if (toadd != null)
{
T correctlyTyped = toadd as T;
if (correctlyTyped != null)
{
retval.Add(correctlyTyped);
}
else
{
retval.AddRange(FindChildren<T>(toadd));
}
}
}
return retval;
}
Related
I've got this class:
public override void Process(TagHelperContext context,
TagHelperOutput output)
{
if (ViewContext != null && PageModel != null)
{
IUrlHelper urlHelper = urlHelperFactory.GetUrlHelper(ViewContext);
TagBuilder result = new TagBuilder("div");
for (int i = 1; i <= PageModel.TotalPages; i++)
{
TagBuilder tag = new TagBuilder("a");
tag.Attributes["href"] = urlHelper.Action(PageAction,
new { productPage = i });
}
tag.InnerHtml.Append(i.ToString());
result.InnerHtml.AppendHtml(tag);
}
output.Content.AppendHtml(result.InnerHtml);
}
However, the 'tag', 'i' and 'result' attributes after the for-loop don't fall in the scope, which shouldn't be the matter if I'm correct. I'm using VS2022 with SDK version 6.0.402.
I'm not sure what you want in the end, but one thing you should pay attention to is that variables defined in a for loop can only be used in a for loop, and variables defined in an if can only be used in an if.
So tag.InnerHtml.Append(i.ToString()); can only be used in a for loop, unless you define an i outside the for loop. Like this:
int k = 0;
for (int i = 1; i <= PageModel.TotalPages; i++)
{
k=i;//The final value of k is PageModel.TotalPages.Count
}
tag.InnerHtml.Append(k.ToString());
If you want to add all i in TagBuilder tag, then it should be like this:
public override void Process(TagHelperContext context,
TagHelperOutput output)
{
TagBuilder result = new TagBuilder("div");
if (ViewContext != null && PageModel != null)
{
IUrlHelper urlHelper = urlHelperFactory.GetUrlHelper(ViewContext);
TagBuilder tag = new TagBuilder("a");
for (int i = 1; i <= PageModel.TotalPages; i++)
{
tag.Attributes["href"] = urlHelper.Action(PageAction,
new { productPage = i });
tag.InnerHtml.Append(i.ToString());
}
result.InnerHtml.AppendHtml(tag);
}
output.Content.AppendHtml(result.InnerHtml);
}
If you only want to add the last entry of PageModel.TotalPages in the TagBuilder tag, it should be like this:
public override void Process(TagHelperContext context,
TagHelperOutput output)
{
TagBuilder result = new TagBuilder("div");
if (ViewContext != null && PageModel != null)
{
IUrlHelper urlHelper = UrlHelperFactory.GetUrlHelper(ViewContext);
TagBuilder tag = new TagBuilder("a");
for (int i = 1; i <= PageModel.TotalPages; i++)
{
tag = new TagBuilder("a");
tag.Attributes["href"] = urlHelper.Action(PageAction,
new { productPage = i });
tag.InnerHtml.Append(i.ToString());
}
result.InnerHtml.AppendHtml(tag);
}
output.Content.AppendHtml(result.InnerHtml);
}
Hope this can help you.
i have created an android application using xamarin.android. the application has a recyclerview that contains a spinner. what i want is when the user selects an item from the spinner, i need to change the value of the corresponding column and row in the datatable and i need the new value to be displayed in the spinner in the recyclerview in the row where the spinner value is selected. the problem is that whenever a value is selected, when another row is clicked, the old value of the spinner is displayed. i tried a lot of ways like the code in the following link: https://www.codeproject.com/articles/1033283/android-recycler-view-with-spinner-item-change-sel, but it didn't work. this is my code:
public class recyclerview_viewholder : RecyclerView.ViewHolder
{
public TextView rownbr, laborname;
public EditText overtime;
public LinearLayout linearLayout;
public Spinner days;
public recyclerview_viewholder(View itemView, Action<int> listener)
: base(itemView)
{
rownbr = itemView.FindViewById<TextView>(Resource.Id.rownbr);
laborname = itemView.FindViewById<TextView>(Resource.Id.laborname);
days = itemView.FindViewById<Spinner>(Resource.Id.days);
overtime = itemView.FindViewById<EditText>(Resource.Id.overtime);
linearLayout = itemView.FindViewById<LinearLayout>(Resource.Id.linearLayout);
itemView.Click += (sender, e) => listener(base.LayoutPosition);
}
public class recyclerviewAdapter : RecyclerView.Adapter
{
// Event handler for item clicks:
public event EventHandler<int> ItemClick;
// public event EventHandler<AdapterView.ItemSelectedEventArgs> SpinnerItemSelectionChanged;
public static DataTable summary_Requests = new DataTable();
//Context context;
public readonly new_schedule context;
public static int selected_pos = -1;
RecyclerView recyclerView;
FloatingActionButton delete;
public recyclerviewAdapter(new_schedule context, DataTable sum_req, RecyclerView recyclerView)
{
this.context = context;
summary_Requests = sum_req;
this.recyclerView = recyclerView;
}
public override RecyclerView.ViewHolder
OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From(parent.Context).
Inflate(Resource.Layout.recycler_view_new_schedule_data, parent, false);
recyclerview_viewholder vh = new recyclerview_viewholder(itemView, OnClick);
vh.days.ItemSelected += (sender, e) =>
{
Spinner spinner = (Spinner)sender;
int position = Convert.ToInt32(spinner.Tag);
summary_Requests.Rows[position]["dayNbr"] = Convert.ToDecimal(spinner.GetItemAtPosition(e.Position).ToString());
};
vh.overtime.TextChanged += (sender, e) =>
{
if (vh.overtime.Text != "")
try
{
int position = vh.LayoutPosition;
summary_Requests.Rows[position]["overtimeHours"] = Convert.ToInt32(vh.overtime.Text);
user.zero_val = "Not_exist";
}
catch (System.FormatException exp)
{
var icon = AppCompatResources.GetDrawable(context.Context, Resource.Drawable.error_ic);
icon.SetBounds(0, 0, 50, 50);
vh.overtime.SetError("unit must be integer not decimal", icon);
user.zero_val = "exits";
}
else if (vh.overtime.Text == "")
{
var icon = AppCompatResources.GetDrawable(context.Context, Resource.Drawable.error_ic);
icon.SetBounds(0, 0, 50, 50);
vh.overtime.SetError("value can not be empty", icon);
user.zero_val = "exits";
}
};
return vh;
}
public override void
OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
recyclerview_viewholder vh = holder as recyclerview_viewholder;
vh.rownbr.Text = summary_Requests.Rows[position]["rowNumber"].ToString();
vh.laborname.Text = summary_Requests.Rows[position]["laborerName"].ToString();
List<decimal> days_data = new List<decimal>();
days_data.Add((decimal)0.5);
days_data.Add((decimal)1);
var adapter = new ArrayAdapter(this.context.Context, Android.Resource.Layout.SimpleSpinnerItem, days_data);
adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);
vh.days.Tag = position;
vh.days.Adapter = adapter;
vh.days.SetSelection(1);
vh.overtime.Text = summary_Requests.Rows[position]["overtimeHours"].ToString();
if (selected_pos == position)
vh.ItemView.SetBackgroundColor(Color.ParseColor("#4fa5d5"));
else
vh.ItemView.SetBackgroundColor(Color.LightGray);
vh.ItemView.Click += (sender, e) =>
{
int pos = vh.LayoutPosition;
user.del_pos = position;
selected_pos = position;
NotifyDataSetChanged();
//fill global variables that need to be passed to detail fragment
};
//delete.Click += delegate
//{
// vh.days.Enabled = false;
//};
}
public DataTable get_dt_final()
{
DataTable final_dt = summary_Requests.Copy();
return final_dt;
}
public override long GetItemId(int position)
{
return position;
}
public void deleteItem(int index)
{
summary_Requests.Rows.RemoveAt(index);
NotifyItemRemoved(index);
}
public override int ItemCount
{
get { return summary_Requests.Rows.Count; }
}
// Raise an event when the item-click takes place:
void OnClick(int position)
{
if (ItemClick != null)
ItemClick(this, position);
// user.req_pos = position;
}
}
}
}
I read the article that you provide, you need to do two things when you change spinner value, firstly, you need to change vegeList's itemPosition quantity by SpinnerItemSelectionChangedEvent, then you need to update TotalAmount in OnBindViewHolder
private void SpinnerItemSelectionChangedEvent(object sender, AdapterView.ItemSelectedEventArgs e)
{
Spinner spinner = (Spinner)sender;
var itemPosition = Convert.ToInt32(spinner.Tag);
//Update the view by Total Amount, after spinner value is been selected.
var currentquantity = vegeList[itemPosition].Quantity;
var selectedQuantity = Convert.ToInt32(spinner.GetItemAtPosition(e.Position).ToString());
if (currentquantity != selectedQuantity)
{
vegeList[itemPosition].Quantity = selectedQuantity;
Madapter.NotifyItemChanged(itemPosition);
}
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
var item = Items[position];
var vh = holder as VegeViewHolder;
var spinnerPos = 0;
var adapter = new ArrayAdapter<String>(Context, Android.Resource.Layout.SimpleSpinnerItem, _quantity);
adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);
vh.Name.Text = item.Name;
vh.Price.Text = string.Format("Price: ${0}", item.Price);
vh.ItemView.Tag = position;
if (item.Quantity > 0)
{
spinnerPos = adapter.GetPosition(item.Quantity.ToString());
vh.TotalAmount.Text = string.Format("${0}", item.Price * item.Quantity);
}
else
{
vh.TotalAmount.Text = "";
}
vh.Quantity.Tag = position; //keep reference to list view row position
vh.Quantity.Adapter = adapter;
vh.Quantity.SetSelection(spinnerPos);
vh.Image.SetImageResource(item.ImageId);
}
I want a frame with a dashed border (as shown in the image). I am looking for UWP Renderer if anyone has any suggestions on that please share them with me. I am stuck with this.
Custom Renderer for Dashed Border of frame in UWP Xamarin
Current there is not such Dashed Border of frame in UWP Xamarin, but you can make it with Rectangle and set available StrokeDashArray to implement it and then use ViewRenderer to render it within Xamarin. We will share DashedBorderRenderer below, for the complete control please refer code sample here.
public class DashedBorderRenderer : ViewRenderer<DashedBorder, DottedBorder>
{
DottedBorder _dottedBorder;
FrameworkElement _navtiveContent;
double defaultPadding = 2;
bool isOpened;
public DashedBorderRenderer()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<DashedBorder> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
_navtiveContent.Loaded -= Native_Loaded;
_navtiveContent.SizeChanged -= Native_SizeChanged;
}
if (e.NewElement != null)
{
if (Control != null)
{
var stroke = Element.DashedStroke == 0 ? Element.DashedStroke : 2.0;
var borderColor = Element.BorderColor.ToWindowsColor() == null ? Element.BorderColor.ToWindowsColor() : Colors.Red;
Control.DashedStroke = new Windows.UI.Xaml.Media.DoubleCollection() { stroke };
Control.StrokeBrush = new Windows.UI.Xaml.Media.SolidColorBrush(borderColor);
}
else
{
_dottedBorder = new DottedBorder();
_navtiveContent = Element.Content.GetOrCreateRenderer().GetNativeElement() as FrameworkElement;
_navtiveContent.Loaded += Native_Loaded;
_navtiveContent.SizeChanged += Native_SizeChanged;
var stroke = Element.DashedStroke == 0 ? 2.0 : Element.DashedStroke;
var borderColor = Element.BorderColor.ToWindowsColor() == null ? Element.BorderColor.ToWindowsColor() : Colors.Red;
_dottedBorder.DashedStroke = new Windows.UI.Xaml.Media.DoubleCollection() { stroke };
_dottedBorder.StrokeBrush = new Windows.UI.Xaml.Media.SolidColorBrush(borderColor);
SetNativeControl(_dottedBorder);
}
}
}
private void Native_SizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateSize(sender);
}
private void Native_Loaded(object sender, RoutedEventArgs e)
{
UpdateSize(sender);
}
private void UpdateSize(object sender)
{
var content = sender as FrameworkElement;
if (content is Windows.UI.Xaml.Controls.Image)
{
if (!isOpened)
{
(content as Windows.UI.Xaml.Controls.Image).ImageOpened += (s, e) =>
{
isOpened = true;
var image = sender as Windows.UI.Xaml.Controls.Image;
_dottedBorder.Height = image.ActualHeight + defaultPadding;
_dottedBorder.Width = image.ActualWidth + defaultPadding;
};
}
else
{
_dottedBorder.Height = content.ActualHeight + defaultPadding;
_dottedBorder.Width = content.ActualWidth + defaultPadding;
}
}
_dottedBorder.Height = content.ActualHeight+defaultPadding;
_dottedBorder.Width = content.ActualWidth + defaultPadding;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
}
}
I am trying to have pull the DisplayAttribute and the DescriptionAttribute from parts of the Swagger Model. For example I may have a Body Parameter which has properties with attributes, which I would also want to be generated in the swagger.json and visible in SwaggerUI.
So far I think the approach that should work would be using a custom filter with swashbuckle. I got a proof of concept using the IParameterFilter which displays the description attribute, not sure if another filter would be better.
Issues:
Finding the key for the schemaRegistry fails for some types, like list.
Need to get the key for the parameter to be generated the same as swagger.
Might need recursion to loop through child properties that contain complex objects.
public class SwaggerParameterFilter : IParameterFilter
{
private SchemaRegistrySettings _settings;
private SchemaIdManager _schemaIdManager;
public SwaggerParameterFilter(SchemaRegistrySettings settings = null)
{
this._settings = settings ?? new SchemaRegistrySettings();
this._schemaIdManager = new SchemaIdManager(this._settings.SchemaIdSelector);
}
public void Apply(IParameter parameter, ParameterFilterContext context)
{
try
{
if (context.ApiParameterDescription?.ModelMetadata?.Properties == null) return;
if (parameter is BodyParameter bodyParameter)
{
string idFor = _schemaIdManager.IdFor(context.ApiParameterDescription.Type);
var schemaRegistry = (SchemaRegistry)context.SchemaRegistry;
//not perfect, crashes with some cases
var schema = schemaRegistry.Definitions[idFor];
//bodyParameter.Schema, this doesn't seem right, no properties
foreach (var modelMetadata in context.ApiParameterDescription.ModelMetadata.Properties)
{
if (modelMetadata is DefaultModelMetadata defaultModelMetadata)
{
//not sure right now how to get the right key for the schema.Properties...
var name = defaultModelMetadata.Name;
name = Char.ToLowerInvariant(name[0]) + name.Substring(1);
if (schema.Properties.ContainsKey(name))
{
var subSchema = schema.Properties[name];
var attributes = defaultModelMetadata.Attributes.Attributes.Select(x => (Attribute)x);
var descriptionAttribute = (DescriptionAttribute)attributes.FirstOrDefault(x => x is DescriptionAttribute);
if (descriptionAttribute != null)
subSchema.Description = descriptionAttribute.Description;
}
}
}
}
}
catch (Exception e)
{
//eat because above is broken
}
}
}
Edit add looping.
public class SwaggerParameterFilter : IParameterFilter
{
private SchemaRegistrySettings _settings;
private SchemaIdManager _schemaIdManager;
public SwaggerParameterFilter(SchemaRegistrySettings settings = null)
{
this._settings = settings ?? new SchemaRegistrySettings();
this._schemaIdManager = new SchemaIdManager(this._settings.SchemaIdSelector);
}
public void Apply(IParameter parameter, ParameterFilterContext context)
{
try
{
if (context.ApiParameterDescription?.ModelMetadata?.Properties == null) return;
//Only BodyParameters are complex and stored in the schema
if (parameter is BodyParameter bodyParameter)
{
var idFor = _schemaIdManager.IdFor(context.ApiParameterDescription.Type);
//not perfect, crashes with some cases
var schema = context.SchemaRegistry.Definitions[idFor];
UpdateSchema(schema, (SchemaRegistry) context.SchemaRegistry, context.ApiParameterDescription.ModelMetadata);
}
}
catch (Exception e)
{
//eat because above is broken
}
}
private void UpdateSchema(Schema schema, SchemaRegistry schemaRegistry, ModelMetadata modelMetadata)
{
if (schema.Ref != null)
{
var schemaReference = schema.Ref.Replace("#/definitions/", "");
UpdateSchema(schemaRegistry.Definitions[schemaReference], schemaRegistry, modelMetadata);
return;
}
if (schema.Properties == null) return;
foreach (var properties in modelMetadata.Properties)
{
if (properties is DefaultModelMetadata defaultModelMetadata)
{
//not sure right now how to get the right key for the schema.Properties...
var name = defaultModelMetadata.Name;
name = Char.ToLowerInvariant(name[0]) + name.Substring(1);
if (schema.Properties.ContainsKey(name) == false) return;
var subSchema = schema.Properties[name];
var attributes = defaultModelMetadata.Attributes.Attributes.Select(x => (Attribute) x).ToList();
var descriptionAttribute =
(DescriptionAttribute) attributes.FirstOrDefault(x => x is DescriptionAttribute);
if (descriptionAttribute != null)
subSchema.Description = descriptionAttribute.Description;
var displayAttribute = (DisplayAttribute) attributes.FirstOrDefault(x => x is DisplayAttribute);
if (displayAttribute != null)
subSchema.Title = displayAttribute.Name;
if (modelMetadata.ModelType.IsPrimitive) return;
UpdateSchema(subSchema, schemaRegistry, defaultModelMetadata);
}
}
}
}
Operation Filter
public class SwaggerOperationFilter : IOperationFilter
{
private SchemaRegistrySettings _settings;
private SchemaIdManager _schemaIdManager;
private IModelMetadataProvider _metadataProvider;
public SwaggerOperationFilter(IModelMetadataProvider metadataProvider, SchemaRegistrySettings settings = null)
{
this._metadataProvider = metadataProvider;
this._settings = settings ?? new SchemaRegistrySettings();
this._schemaIdManager = new SchemaIdManager(this._settings.SchemaIdSelector);
}
public void Apply(Operation operation, OperationFilterContext context)
{
try
{
foreach (var paramDescription in context.ApiDescription.ParameterDescriptions)
{
if (paramDescription?.ModelMetadata?.Properties == null)
{
continue;
}
if (paramDescription.ModelMetadata.ModelType.IsPrimitive)
{
continue;
}
if (paramDescription.ModelMetadata.ModelType == typeof(string))
{
continue;
}
var idFor = _schemaIdManager.IdFor(paramDescription.Type);
var schema = context.SchemaRegistry.Definitions[idFor];
UpdateSchema(schema, (SchemaRegistry)context.SchemaRegistry, paramDescription.ModelMetadata);
}
}
catch (Exception e)
{
//eat because above is broken
}
}
private void UpdateSchema(Schema schema, SchemaRegistry schemaRegistry, ModelMetadata modelMetadata)
{
if (schema.Ref != null)
{
var schemaReference = schema.Ref.Replace("#/definitions/", "");
UpdateSchema(schemaRegistry.Definitions[schemaReference], schemaRegistry, modelMetadata);
return;
}
if (schema.Type == "array")
{
if (schema.Items.Ref != null)
{
var schemaReference = schema.Items.Ref.Replace("#/definitions/", "");
var modelTypeGenericTypeArgument = modelMetadata.ModelType.GenericTypeArguments[0];
modelMetadata = _metadataProvider.GetMetadataForType(modelTypeGenericTypeArgument);
UpdateSchema(schemaRegistry.Definitions[schemaReference], schemaRegistry, modelMetadata);
}
return;
}
if (schema.Properties == null) return;
foreach (var properties in modelMetadata.Properties)
{
if (properties is DefaultModelMetadata defaultModelMetadata)
{
//not sure right now how to get the right key for the schema.Properties...
var name = defaultModelMetadata.Name;
name = Char.ToLowerInvariant(name[0]) + name.Substring(1);
if (schema.Properties.ContainsKey(name) == false) return;
var subSchema = schema.Properties[name];
var attributes = defaultModelMetadata.Attributes.Attributes.Select(x => (Attribute)x).ToList();
var descriptionAttribute =
(DescriptionAttribute)attributes.FirstOrDefault(x => x is DescriptionAttribute);
if (descriptionAttribute != null)
subSchema.Description = descriptionAttribute.Description;
var displayAttribute = (DisplayAttribute)attributes.FirstOrDefault(x => x is DisplayAttribute);
if (displayAttribute != null)
subSchema.Title = displayAttribute.Name;
if (defaultModelMetadata.ModelType.IsPrimitive) return;
UpdateSchema(subSchema, schemaRegistry, defaultModelMetadata);
}
}
}
}
So after some troubleshooting this seems to work for me but may need modification for other cases.
public class SwashbuckleAttributeReaderDocumentFilter : IDocumentFilter
{
private readonly SchemaIdManager _schemaIdManager;
private readonly IModelMetadataProvider _metadataProvider;
private List<string> _updatedSchemeList;
public SwashbuckleAttributeReaderDocumentFilter(IModelMetadataProvider metadataProvider, SchemaRegistrySettings settings = null)
{
_metadataProvider = metadataProvider;
var registrySettings = settings ?? new SchemaRegistrySettings();
_schemaIdManager = new SchemaIdManager(registrySettings.SchemaIdSelector);
}
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
{
_updatedSchemeList = new List<string>();
foreach (var apiDescription in context.ApiDescriptions)
{
foreach (var responseTypes in apiDescription.SupportedResponseTypes)
{
ProcessModelMetadata(context, responseTypes.ModelMetadata);
}
foreach (var paramDescription in apiDescription.ParameterDescriptions)
{
ProcessModelMetadata(context, paramDescription.ModelMetadata);
}
}
}
private void ProcessModelMetadata(DocumentFilterContext context, ModelMetadata currentModelMetadata)
{
if (currentModelMetadata?.Properties == null)
{
return;
}
if (currentModelMetadata.ModelType.IsValueType)
{
return;
}
if (currentModelMetadata.ModelType == typeof(string))
{
return;
}
if (currentModelMetadata.ModelType.IsGenericType)
{
foreach (var modelType in currentModelMetadata.ModelType.GenericTypeArguments)
{
var modelMetadata = _metadataProvider.GetMetadataForType(modelType);
UpdateSchema(context.SchemaRegistry, modelMetadata);
}
}
else if (currentModelMetadata.IsCollectionType)
{
var modelType = currentModelMetadata.ModelType.GetElementType();
var modelMetadata = _metadataProvider.GetMetadataForType(modelType);
UpdateSchema(context.SchemaRegistry, modelMetadata);
}
else
{
UpdateSchema(context.SchemaRegistry, currentModelMetadata);
}
}
public static void SetSchema(Schema schema, ModelMetadata modelMetadata)
{
if (!(modelMetadata is DefaultModelMetadata metadata)) return;
var attributes = GetAtributes(metadata);
SetDescription(attributes, schema);
SetTitle(attributes, schema);
}
private static List<Attribute> GetAtributes(DefaultModelMetadata modelMetadata)
{
return modelMetadata.Attributes.Attributes.Select(x => (Attribute)x).ToList();
}
private static void SetTitle(List<Attribute> attributes, Schema schema)
{
//LastOrDefault because we want the attribute from the dervived class.
var displayAttribute = (DisplayNameAttribute)attributes.LastOrDefault(x => x is DisplayNameAttribute);
if (displayAttribute != null)
schema.Title = displayAttribute.DisplayName;
}
private static void SetDescription(List<Attribute> attributes, Schema schema)
{
//LastOrDefault because we want the attribute from the dervived class. not sure if this works.
var descriptionAttribute = (DescriptionAttribute)attributes.LastOrDefault(x => x is DescriptionAttribute);
if (descriptionAttribute != null)
schema.Description = descriptionAttribute.Description;
}
private void UpdateSchema(ISchemaRegistry schemaRegistry, ModelMetadata modelMetadata, Schema schema = null)
{
if (modelMetadata.ModelType.IsValueType) return;
if (modelMetadata.ModelType == typeof(string)) return;
var idFor = _schemaIdManager.IdFor(modelMetadata.ModelType);
if (_updatedSchemeList.Contains(idFor))
return;
if (schema == null || schema.Ref != null)
{
if (schemaRegistry.Definitions.ContainsKey(idFor) == false) return;
schema = schemaRegistry.Definitions[idFor];
}
_updatedSchemeList.Add(idFor);
SetSchema(schema, modelMetadata);
if (schema.Type == "array")//Array Schema
{
var metaData = _metadataProvider.GetMetadataForType(modelMetadata.ModelType.GenericTypeArguments[0]);
UpdateSchema(schemaRegistry, metaData);
}
else//object schema
{
if (schema.Properties == null)
{
return;
}
foreach (var properties in modelMetadata.Properties)
{
if (!(properties is DefaultModelMetadata defaultModelMetadata))
{
continue;
}
var name = ToLowerCamelCase(defaultModelMetadata.Name);
if (schema.Properties.ContainsKey(name) == false)
{
//when this doesn't match the json object naming.
return;
}
var subSchema = schema.Properties[name];
SetSchema(subSchema, defaultModelMetadata);
UpdateSchema(schemaRegistry, defaultModelMetadata, subSchema);
}
}
}
private static string ToLowerCamelCase(string inputString)
{
if (inputString == null) return null;
if (inputString == string.Empty) return string.Empty;
if (char.IsLower(inputString[0])) return inputString;
return inputString.Substring(0, 1).ToLower() + inputString.Substring(1);
}
}
How to allow Setting Tabindex within the c1 FlexGrid in such a way that it skips a particular column in the c1 FlexGrid.
Is there something I can too do this
Thanks!
There might be a better way, but here's one approach:
public partial class Form1 : Form
{
private Int32 _colIdxToSkip = 4; //Remember, there's an extra column if "Row Headers" are turned on!
private Keys _lastKeys = Keys.None;
public Form1()
{
InitializeComponent();
flexGrid.KeyActionTab = C1.Win.C1FlexGrid.KeyActionEnum.MoveAcross;
}
private void flexGrid_BeforeRowColChange(Object sender, C1.Win.C1FlexGrid.RangeEventArgs e)
{
if (_lastKeys == Keys.Tab && e.OldRange.r1 == e.NewRange.r1 && e.NewRange.c1 == _colIdxToSkip)
{
if (_colIdxToSkip == flexGrid.Cols.Count - 1)
{
flexGrid.Row = (flexGrid.Row == flexGrid.Rows.Count - 1 ? flexGrid.Rows.Fixed : flexGrid.Row + 1);
flexGrid.Col = flexGrid.Cols.Fixed;
}
else
flexGrid.Col = _colIdxToSkip + 1;
e.Cancel = true;
}
}
private void flexGrid_KeyDown(Object sender, KeyEventArgs e)
{
_lastKeys = e.KeyCode;
}
}