Xamarin Android: How to delete multiple itens in recyclerview - c#

Hello everyone my name is Taniguchi
I've implemented a recyclerview and inserted a button navigation view to delete selected items.
When i click on a item in the recyclerview i select a item. I inserted a collection to store the item position when i click and when the item is unselected i remove the item position from collection
I was able to delete multiple itens on recyclerview but one item is being deleted wrong, for example. I select two itens position 0 and position 1 i click to delete both, but instead of delete position 1, the item position 3 is removed instead and the postion 2 item continues to be selected.
How can i remove itens properly ?
my recyclerview adapter:
public class RecyclerAdapter : RecyclerView.Adapter, View.IOnClickListener
{
private List<Email> mEmails;
private Activity mActivity;
public static int listPosition;
private List<collectPosition> mcollectID;
private int position_collectID = 0;
private Boolean isSelected = false;
public Boolean IsSelected()
{
return isSelected;
}
public void setSelected(Boolean selected)
{
isSelected = selected;
}
public RecyclerAdapter(List<Email> emails, Activity activity)
{
mEmails = emails;
mActivity = activity;
}
public override int ItemCount => mEmails.Count;
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View row = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.row, parent, false);
RecyclerViewHolder view = new RecyclerViewHolder(row);
return view;
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
RecyclerViewHolder myHolder = holder as RecyclerViewHolder;
myHolder.mDate.Text = ((Email)mEmails[position]).date;
myHolder.mSubject.Text = ((Email)mEmails[position]).Subject;
myHolder.mMessage.Text = ((Email)mEmails[position]).Message;
myHolder.ItemView.SetBackgroundColor(((Email)mEmails[position]).IsSelected() ? Color.LightBlue : Color.Transparent);
myHolder.ItemView.Tag = position;
myHolder.ItemView.SetOnClickListener(this);
}
void View.IOnClickListener.OnClick(View v)
{
int position = (int)v.Tag;
listPosition = (int)v.Tag;
((Email)mEmails[position]).setSelected(!((Email)mEmails[position]).IsSelected());
v.SetBackgroundColor(((Email)mEmails[position]).IsSelected() ? Color.LightBlue : Color.Transparent);
if (mcollectID == null)
mcollectID = new List<collectPosition>();
if (((Email)mEmails[position]).IsSelected())
{
mcollectID.Add(new collectPosition() { getPosition = (int)v.Tag });
position_collectID = position_collectID + 1;
}
else
{
position_collectID = position_collectID - 1;
mcollectID.RemoveAt(position_collectID);
}
Toast.MakeText(v.Context, "Click : " + ((Email)mEmails[position]).date + "---" + position, ToastLength.Short).Show();
}
public void DeleteItem()
{
if (mEmails != null && mEmails.Count > 0)
{
foreach (collectPosition collId in mcollectID)
{
mEmails.RemoveAt(collId.getPosition);
NotifyItemChanged(collId.getPosition);
NotifyDataSetChanged();
}
}
}
}
where i calling the recyclerview:
public class MainActivity : AppCompatActivity
{
public static RecyclerView mRecyclerView;
public static RecyclerView.LayoutManager mLayoutManager;
public RecyclerView.ViewHolder holder;
public static BottomNavigationView bottomnavigationview1;
public RecyclerAdapter mAdapter;
public static List<Email> mEmails;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Xamarin.Essentials.Platform.Init(this, bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
mRecyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerViwer);
mRecyclerView.AddItemDecoration(new DividerItemDecoration(mRecyclerView.Context, DividerItemDecoration.Vertical));
mRecyclerView.HasFixedSize = true;
SetupList();
//Create our layout Manager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.SetLayoutManager(mLayoutManager);
mAdapter = new RecyclerAdapter(mEmails, this);
mRecyclerView.SetAdapter(mAdapter);
bottomnavigationview1 = FindViewById<BottomNavigationView>
(Resource.Id.bottom_navigation);
bottomnavigationview1.NavigationItemSelected += BottomNavigation_NavigationItemSelected;
}
private void SetupList()
{
mEmails = new List<Email>();
mEmails.Add(new Email() { date = "9/25/2019", Subject = "Wanna Hang Out?", Message = "I ' ll be around tomorrow!!" });
mEmails.Add(new Email() { date = "9/25/2019", Subject = "Wanna Hang Out?", Message = "I ' ll be around tomorrow!!" });
mEmails.Add(new Email() { date = "9/25/2019", Subject = "Wanna Hang Out?", Message = "I ' ll be around tomorrow!!" });
mEmails.Add(new Email() { date = "9/24/2019", Subject = "Wanna Hang Out?", Message = "I ' ll be around tomorrow!!" });
mEmails.Add(new Email() { date = "9/24/2019", Subject = "Wanna Hang Out?", Message = "I ' ll be around tomorrow!!" });
}

if you just want to delete the items which you select,you don't need to store the position,as you have saved the check status,the property IsSelected in your Email model.
you could use it directly like :
void View.IOnClickListener.OnClick(View v)
{
int position = (int)v.Tag;
listPosition = (int)v.Tag;
((Email)mEmails[position]).setSelected(!((Email)mEmails[position]).IsSelected());
v.SetBackgroundColor(((Email)mEmails[position]).IsSelected() ? Color.LightBlue : Color.Transparent);
Toast.MakeText(v.Context, "Click : " + ((Email)mEmails[position]).date + "---" + position, ToastLength.Short).Show();
}
public void DeleteItem()
{
if (mEmails != null && mEmails.Count > 0)
{
foreach (Email email in mEmails.ToList())
{
if (email.IsSelected())
{
mEmails.Remove(email);
}
}
NotifyDataSetChanged();
}
}

Related

C# - Winforms - Combobox - Avoid selecting the first item updating the datasource

I have a combobox in my application, where items are loaded asynchronously depending on a search text you can enter in the text field.
This works fine, but every time the text of the first item is automatically selected during updating the datasource of the combobox.
This leads to unintended behaviour, because I need to have the search text entered by the user to stay in the textfield of the combobox until a selection is done by the user and not automatically overwrite the text with the first entry.
This is my code:
public partial class ProductGroupDescription : UserControl, Interfaces.TabPages.ITabPageProductGroupDescription
{
private Services.IProductGroupDescriptionService _ApplicationService;
public BindingList<ProductGroup> ProductGroups { get; set; } = new BindingList<ProductGroup>();
public string ProductGroupSearchText { get; set; } = string.Empty;
public ProductGroupDescription(Services.IProductGroupDescriptionService applicationService)
{
InitializeComponent();
InitialSetupControls();
_ApplicationService = applicationService;
}
public void InitialSetupControls()
{
var pgBindingSource = new BindingSource();
pgBindingSource.DataSource = ProductGroups;
Cbo_ProductGroup.DataSource = pgBindingSource.DataSource;
Cbo_ProductGroup.DataBindings.Add("Text", ProductGroupSearchText, "");
}
private async void Cbo_ProductGroup_TextChanged(object sender, EventArgs e)
{
if (Cbo_ProductGroup.Text.Length >= 2)
{
ProductGroupSearchText = Cbo_ProductGroup.Text;
Cbo_ProductGroup.SelectedIndex = -1;
bool withStopFlagged = Chk_StopFlag_PGs_Included.Checked;
List<ProductGroup> list = await _ApplicationService.GetProductGroupBySearchString(ProductGroupSearchText, withStopFlagged);
if (list != null && list.Count > 0)
{
ProductGroups.Clear();
list.ForEach(item => ProductGroups.Add(item));
Cbo_ProductGroup.DroppedDown = Cbo_ProductGroup.Items.Count > 0 && Cbo_ProductGroup.Focused;
}
}
}
}
I tried to set Cbo_ProductGroup.SelectedIndex = -1, but it does not solve my issue here.
I also saw this on SO: Prevent AutoSelect behavior of a System.Window.Forms.ComboBox (C#)
But is there really no simpler solution to this issue?
I got it to work now.
It worked, when I removed the binding of the text field of the combobox
Cbo_ProductGroup.DataBindings.Add("Text", ProductGroupSearchText, "");
and set the new (old) value directly to the text field of the combobox.
Cbo_ProductGroup.Text = searchText;
In this case, a new event Text_Changed is fired and so the application has a infinite loop. So I used a property (ShouldTextChangedEventBeIgnored), if the Text_Changed event should be ignored.
Thanks to #CaiusJard for many hints in the comments.
This is my final code:
public partial class ProductGroupDescription : UserControl, Interfaces.TabPages.ITabPageProductGroupDescription
{
private ApplicationLogic.Interfaces.Services.IProductGroupDescriptionService _ApplicationService;
public BindingList<ProductGroup> ProductGroups { get; set; } = new BindingList<ProductGroup>();
public bool ShouldTextChangedEventBeIgnored { get; set; } = false;
public ProductGroupDescription(ApplicationLogic.Interfaces.Services.IProductGroupDescriptionService applicationService)
{
_ApplicationService = applicationService;
InitializeComponent();
InitialSetupControls();
}
public void InitialSetupControls()
{
var pgBindingSource = new BindingSource();
pgBindingSource.DataSource = ProductGroups;
Cbo_ProductGroup.DataSource = pgBindingSource.DataSource;
}
private async Task<List<ProductGroup>> LoadProductGroupItems(string searchText)
{
bool withStopFlagged = Chk_StopFlag_PGs_Included.Checked;
return await _ApplicationService.GetProductGroupBySearchString(searchText, withStopFlagged);
}
private async Task SetProductGroupSearchBoxItems(List<ProductGroup> list, string searchText)
{
await Task.Run(() =>
{
if (list != null && list.Count > 0)
{
ShouldTextChangedEventBeIgnored = true;
Cbo_ProductGroup.Invoke((c) =>
{
ProductGroups.Clear();
list.ForEach(item => ProductGroups.Add(item));
c.DroppedDown = c.Items.Count > 0 && c.Focused;
c.Text = searchText;
c.Select(c.Text.Length, 0);
});
ShouldTextChangedEventBeIgnored = false;
}
});
}
private async void Cbo_ProductGroup_TextChanged(object sender, EventArgs e)
{
try
{
if (Cbo_ProductGroup.Text.Length >= 2 && ShouldTextChangedEventBeIgnored == false)
{
string searchText = Cbo_ProductGroup.Text;
List<ProductGroup> list = await LoadProductGroupItems(Cbo_ProductGroup.Text);
await SetProductGroupSearchBoxItems(list, searchText);
}
}
catch(Exception ex)
{
System.Diagnostics.Trace.Write(ex);
}
}
}

How to get the clicked item from MpAndroidChart(UltimateXF) in Xamarin forms

I'm using MpAndroidChart(UltimateXF) for my app. I created the piechart successfully but I am unable to create a event listener to get the clicked item when user touched one of piechart item.
This is my UltimateXF library
https://nuget.org/packages/UltimateXF/
This is my code....
public partial class HomePage : ContentPage
{
public HomePage ()
{
InitializeComponent ();
var entries = new List<PieEntry>();
entries.Add(new PieEntry(40, "Life"));
entries.Add(new PieEntry(60, "General"));
var dataSet4 = new PieDataSet(entries, "")
{
Colors = new List<Color>()
{
Color.Accent, Color.Chocolate
},
ValueLineColor = Color.Blue,
SliceSpace = 2f,
ValueFormatter = new CustomPercentDataSetValueFormatter()
};
var data4 = new PieChartData(dataSet4)
{
};
var dataSet5 = new PieDataSet(entries, "")
{
};
pieChart.ChartData = data4;
pieChart.RotateEnabled = false;
}
}
public class CustomPercentDataSetValueFormatter : IDataSetValueFormatter
{
public string GetFormattedValue(float value, int dataSetIndex)
{
return value + "%";
}
}

Xamarin.Forms: NavigationController is null in PageRenderer

I am trying to use PageRenderer to customize/reposition elements of ToolbarItem for iOS but here NavigationController throwing null reference exception.
Below my code
public class MyNavigationRenderer: PageRenderer
{
public new MyNavigationBar Element
{
get { return (MyNavigationBar)base.Element; }
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var LeftNavList = new List<UIBarButtonItem>();
var rightNavList = new List<UIBarButtonItem>();
var navigationItem = this.NavigationController.TopViewController.NavigationItem;
for (var i = 0; i < Element.ToolbarItems.Count; i++)
{
var reorder = (Element.ToolbarItems.Count - 1);
var ItemPriority = Element.ToolbarItems[reorder - i].Priority;
if (ItemPriority == 1)
{
UIBarButtonItem LeftNavItems = navigationItem.RightBarButtonItems[i];
LeftNavList.Add(LeftNavItems);
}
else if (ItemPriority == 0)
{
UIBarButtonItem RightNavItems = navigationItem.RightBarButtonItems[i];
rightNavList.Add(RightNavItems);
}
}
navigationItem.SetLeftBarButtonItems(LeftNavList.ToArray(), false);
navigationItem.SetRightBarButtonItems(rightNavList.ToArray(), false);
}
}
Below MyNavigationBar.cs class in portable/shared forms project
public class MyNavigationBar : NavigationPage
{
public MyNavigationBar(Page content) : base(content)
{
Init();
}
private void Init()
{
this.ToolbarItems.Add(new ToolbarItem() { Icon = "kid", Priority = 0, Order = ToolbarItemOrder.Primary });
this.ToolbarItems.Add(new ToolbarItem() { Text = "License", Priority = 0, Order = ToolbarItemOrder.Primary });
}
}
App starting
public App ()
{
InitializeComponent();
MainPage = new MyNavigationBar(new LoginPage());
}
See below screenshot getting exception
I faced this issue, but in my case, I was trying to get NavigationController from content page which didn't had NavigationController, make sure you null check before calling TopViewController,
var navController = this.NavigationController;
if(navController == null)
{
return;
}
UINavigationItem navigationItem = navController.TopViewController.NavigationItem;
For example,
When User opens the app, he will be presented with Login page, which didn't had any Navigation Bar.

What is the best way to return duplicate values from a list on the same ListView row in the GetView() Method?

I have some data in a list that shows for example the Item Number, Line Number, Quantity, and Pack Size of an order. The problem is that some lines on the order will have the same item number but different quantities, pack sizes or both. For example :
Order# Line# Item# Qty Pack Size
100 1 12345 640 (10#64)
100 1 12345 128 (1#128)
100 2 23124 48 (1#48)
100 3 53425 80 (1#80)
Shown above for item 12345 they have ordered a total of 768 pieces but for 640 of those pieces they would like to receive 10 packs containing 64 pieces each and they would like 128 of the pieces in just one pack. When the ListView is created naturally it will create 4 rows, one row for each of the rows in the list. I would like it to only show 3 rows one for each Item# and if there are duplicate items it should add the quantities and combine the pack sizes into one row. I have tried doing something like this trying to force it to do what i wanted but it obviously does not work that well. I am fairly new to Android and ListViews so I am hoping that there is a better way to accomplish this. Can anyone point me in the right direction?
public class LoadInfoViewAdapter : BaseAdapter<Items>
{
private List<Items> lItems;
private Context gContext;
private string gLoadnStop;
private string gPacks;
private decimal gtotal;
int total;
public LoadInfoViewAdapter(Context context, List<Items> loadinfo, string LoadnStop)
{
lItems = loadinfo;
gContext = context;
gLoadnStop = LoadnStop;
}
public override int Count
{
get { return lItems.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override Items this[int position]
{
get { return lItems[position]; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
if (row == null)
{
row = LayoutInflater.From(gContext).Inflate(Resource.Layout.LoadInfoItems_Row, null);
}
//If the item at the current position is the same as the item in the next position add the qty and combine the packs
if (lItems[position].ItemNo == lItems[position + 1].ItemNo)
{
string itemno = lItems[position].ItemNo;
int count = 0;
row.FindViewById<TextView>(Resource.Id.txtItemNo).Text = lItems[position].ItemNo.Trim();
row.FindViewById<TextView>(Resource.Id.txtLineNo).Text = lItems[position].LineNum.Trim();
foreach (var item in lItems.Where(r => r.ItemNo == itemno))
{
if (count == 0)
{
gPacks = lItems[position].Pack.ToString().Trim();
gtotal = lItems[position].Qty;
}
else
{
gPacks = lItems[position + 1].Pack.ToString().Trim() + ", " + gPacks;
gtotal = lItems[position + 1].Qty + gtotal;
}
count = +1;
}
row.FindViewById<TextView>(Resource.Id.txtQuantity).Text = gtotal + " (" + gPacks + ") ";
gtotal = 0;
}
//check to see if the current item is was the same as the previous item added. If so I dont want to create a row for that item.
else if (lItems[position].ItemNo == lItems[position - 1].ItemNo)
{
//Not too sure what would be the best code to go here
}
//if it has no duplicate create the row like normal
else
{
row.FindViewById<TextView>(Resource.Id.txtItemNo).Text = lItems[position].ItemNo.Trim();
row.FindViewById<TextView>(Resource.Id.txtLineNo).Text = lItems[position].LineNum.Trim();
row.FindViewById<TextView>(Resource.Id.txtQuantity).Text = lItems[position].Qty.ToString().Trim() + lItems[position].Pack.ToString().Trim();
}
return row;
}
I would like it to return something like this :
12345 1 768((10#64),(1#128))
23124 2 48(1#48)
53425 3 80(1#80)
For whatever reason it will do what i was hoping for the duplicate item numbers but it sometimes duplicates a different item in the list like:
12345 1 768((10#64),(1#128))
23124 2 48(1#48)
53425 3 80(1#80)
23124 2 48(1#48)
Anyone got any suggestions?
Your fundamental issue is that the Items indexer is stating that you have 4 items available, but your desired result is 3 items.
This isn't really a task that you should be solving in your BaseAdapter. You should be processing the list in advance and reducing to your target 3 items BEFORE passing it into your base adapter.
Also, you should try and avoid using FindViewFromId in GetView, unless the convertView is null. In order to do this, you can pack the previously identified Views into the Tag property: that's what it's for, see https://blog.xamarin.com/creating-highly-performant-smooth-scrolling-android-listviews/
If you really want to do it all in your base adapter, then convert the items in the constructor, something like this:
public class LoadInfoViewAdapter : BaseAdapter<Items>
{
private List<CondensedItems> cItems;
private Context gContext;
public LoadInfoViewAdapter(Context context, List<Items> loadinfo, string LoadnStop)
{
gContext = context;
gLoadnStop = LoadnStop;
// Get all of the unique item numbers.
var uniqueItemNos = loadInfo.Select(x => x.ItemNo).Distinct();
cItems = new List<CondensedItem>();
foreach(string uniqueItem in uniqueItemNos)
{
// Gets all of the items with the target itemNo. If you want to avoid merging them all, you need to do some work checking for sequential indexes or something similar.
var matchingItems = loadInfo.Select(x => x.ItemNo == uniqueItem).ToList();
var lineNo = matchingItems[0].LineNo;
var qty = matchingItems.Sum(x => x.Qty).ToString();
StringBuilder packsSB = new StringBuilder();
foreach(var item in matchingItems)
{
packs.Append(item.Pack + ",");
}
string packs = packsSB.ToString().Trim(',');
cItems.Add(
new CondensedItem
{
ItemNo = uniqueItem,
LineNo = lineNo,
Packs = $"{qty}({packs})"
});
}
}
public override int Count
{
get { return cItems.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override Items this[int position]
{
get { return cItems[position]; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
CondensedViewHolder viewHolder;
if (row == null)
{
row = LayoutInflater.From(gContext).Inflate(Resource.Layout.LoadInfoItems_Row, null);
viewHolder = new CondensedViewHolder
{
ItemView = row.FindViewById<TextView>(Resource.Id.txtItemNo),
LineView = row.FindViewById<TextView>(Resource.Id.txtLineNo),
PacksView = row.FindViewById<TextView>(Resource.Id.txtQuantity)
}
row.Tag = viewHolder;
}
else
{
viewHolder = row.Tag as CondensedViewHolder;
}
viewHolder.ItemView.Text = cItems[position].ItemNo;
viewHolder.LineView.Text = cItems[position].LineNo;
viewHolder.PacksView.Text = cItems[position].Packs;
return row;
}
private class CondensedItem
{
string ItemNo { get; set; }
string LineNo { get; set; }
string Packs { get; set; }
}
private class CondensedViewHolder : Java.Lang.Object
{
public TextView ItemView { get; set; }
public TextView LineView { get; set; }
public TextView PacksView { get; set; }
}
}

Umbraco 4.5.2 - Creating custom umbraco Data Editor Setting Types

I can't seem to find anything on how to edit the data editor settings before umbraco 6.2 (Juno). Is there any simple way, it must be possible. If you don't understand what i mean i want to do the same as http://www.nibble.be/?p=96 - just for umbraco 4.5.2.
Thanks :)
You need to make 3 classes Class 1 DataEditor
public class DataEditor : System.Web.UI.UpdatePanel, umbraco.interfaces.IDataEditor
{
public MWCropperDataEditor(umbraco.interfaces.IData Data, string Configuration)
{
_data = Data;
}
public virtual bool TreatAsRichTextEditor
{
get { return false; }
}
public bool ShowLabel
{
get { return true; }
}
public Control Editor { get { return this; } }
public void Save()
{
this._data.Value = "data;
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
imageUpload = new FileUpload();
imageUpload.ID = "imageUpload";
//shows Image
cropImage = new System.Web.UI.WebControls.Image();
cropImage.Width = width;
cropImage.Height = height;
cropImage.ImageUrl = this._data.Value.ToString();
//Shows dropdown
locationDropDown = new DropDownList();
AddItemsToDropDown();
lblInfo = new Label();
lblInfo.Attributes.Add("id", "title" + base.ClientID);
lblCropInfo = new Label();
lblCropInfo.Text = "Crop Location: ";
base.ContentTemplateContainer.Controls.Add(lblInfo);
base.ContentTemplateContainer.Controls.Add(imageUpload);
base.ContentTemplateContainer.Controls.Add(new LiteralControl("<br/>"));
base.ContentTemplateContainer.Controls.Add(new LiteralControl("<br/>"));
base.ContentTemplateContainer.Controls.Add(lblCropInfo);
base.ContentTemplateContainer.Controls.Add(locationDropDown);
base.ContentTemplateContainer.Controls.Add(new LiteralControl("<br/>"));
base.ContentTemplateContainer.Controls.Add(new LiteralControl("<br/>"));
base.ContentTemplateContainer.Controls.Add(cropImage);
}
}
class 2 DataType
public class MWCropperDataType : umbraco.cms.businesslogic.datatype.BaseDataType, umbraco.interfaces.IDataType
{
private umbraco.interfaces.IDataEditor _Editor;
private umbraco.interfaces.IData _baseData;
private MWCropperPrevalueEditor _prevalueeditor;
public override umbraco.interfaces.IDataEditor DataEditor
{
get
{
if (_Editor == null)
_Editor = new MWCropperDataEditor(Data, ((MWCropperPrevalueEditor)PrevalueEditor).Configuration);
return _Editor;
}
}
public override umbraco.interfaces.IData Data
{
get
{
if (_baseData == null)
_baseData = new umbraco.cms.businesslogic.datatype.DefaultData(this);
return _baseData;
}
}
public override Guid Id
{
get { return new Guid("71518B4E-B1A5-11DD-A22C-8AAA56D89593"); }
}
public override string DataTypeName
{
get { return "MWCropper"; }
}
public override umbraco.interfaces.IDataPrevalue PrevalueEditor
{
get
{
if (_prevalueeditor == null)
_prevalueeditor = new MWCropperPrevalueEditor(this);
return _prevalueeditor;
}
}
}
Class 3 PrevalueEditor
public class MWCropperPrevalueEditor : System.Web.UI.WebControls.PlaceHolder, umbraco.interfaces.IDataPrevalue
{
#region IDataPrevalue Members
// referenced datatype
private umbraco.cms.businesslogic.datatype.BaseDataType _datatype;
private TextBox _txtWidth;
private TextBox _txtHeight;
public MWCropperPrevalueEditor(umbraco.cms.businesslogic.datatype.BaseDataType DataType)
{
_datatype = DataType;
setupChildControls();
}
private void setupChildControls()
{
_txtWidth = new TextBox();
_txtWidth.ID = "txtWidth";
_txtWidth.CssClass = "umbEditorTextField";
Controls.Add(_txtWidth);
_txtHeight = new TextBox();
_txtHeight.ID = "txtHeight";
_txtHeight.CssClass = "umbEditorTextField";
Controls.Add(_txtHeight);
}
public Control Editor
{
get
{
return this;
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!Page.IsPostBack)
{
if (Configuration.Length > 0)
{
string[] value = Configuration.Split(new char[]{';'});
_txtWidth.Text = value[0];
_txtHeight.Text = value[1];
}
else
{
_txtHeight.Text = "100";
_txtWidth.Text = "100";
}
}
}
public void Save()
{
_datatype.DBType = (umbraco.cms.businesslogic.datatype.DBTypes)Enum.Parse(typeof(umbraco.cms.businesslogic.datatype.DBTypes), DBTypes.Ntext.ToString(), true);
string data = _txtWidth.Text+";"+_txtHeight.Text;
SqlHelper.ExecuteNonQuery("delete from cmsDataTypePreValues where datatypenodeid = #dtdefid",
SqlHelper.CreateParameter("#dtdefid", _datatype.DataTypeDefinitionId));
SqlHelper.ExecuteNonQuery("insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (#dtdefid,#value,0,'')",
SqlHelper.CreateParameter("#dtdefid", _datatype.DataTypeDefinitionId), SqlHelper.CreateParameter("#value", data));
}
protected override void Render(HtmlTextWriter writer)
{
writer.WriteLine("<table>");
writer.Write("<tr><th>Width:</th><td>");
_txtWidth.RenderControl(writer);
writer.Write("</td></tr>");
writer.Write("<tr><th>Height:</th><td>");
_txtHeight.RenderControl(writer);
writer.Write("</td></tr>");
writer.Write("</table>");
}
public string Configuration
{
get
{
object conf =
SqlHelper.ExecuteScalar<object>("select value from cmsDataTypePreValues where datatypenodeid = #datatypenodeid",
SqlHelper.CreateParameter("#datatypenodeid", _datatype.DataTypeDefinitionId));
if (conf != null)
return conf.ToString();
else
return "";
}
}
#endregion
public static ISqlHelper SqlHelper
{
get
{
return Application.SqlHelper;
}
}
}
I hope this can help you get started :)
Btw this also works for umbraco 6.2
Settings are called prevalues and you need a PrevalueEditor class that implements IDataPrevalue. Have a look at an example in this blog post:
http://www.eyecatch.no/blog/my-first-umbraco-datatype---part-2-rendering-a-recaptcha-control.aspx
This nibble post concerns doing a similar thing for v4.5 and prior, there is also a link within this for an even older version that I followed a while ago and found very helpful.
http://www.nibble.be/?p=62

Categories