Standard way to render datasource of a sublayout - Sitecore - sitecore

This works for me, but want to know it's the correct method or there is a better way, to display an item that is set as a datasource to a sublayout.
sample.ascx
<sc:Text ID="txtHeader" runat="server" Field="Header" />
<br/>
<sc:Image ID="imgMotif" runat="server" Field="Motif Left" />
<br/>
<!-- some more controls -->
sample.ascx.cs
private void BindData()
{
Item introItem = GetItemFromDatasource((Sublayout)this.Parent);
if(introItem != null)
{
txtHeader.Item = introItem;
imgMotif.Item = introItem;
//..and so on..
}
}
private Item GetItemFromDatasource(Sublayout sublayout)
{
Item dataSource = null;
if (sublayout != null)
{
Guid dataSourceId;
if (Guid.TryParse(sublayout.DataSource, out dataSourceId))
dataSource = Sitecore.Context.Database.GetItem(new ID(dataSourceId));
}
return dataSource;
}

I suggest your sublayouts to inherit from a sublayout base.
Your SublayoutBase will look like:
public class SublayoutBase : UserControl
{
private Item _dataSource;
public Item DataSource
{
get
{
if (_dataSource == null)
{
if (Parent is Sublayout)
{
var sublayout = (Sitecore.Web.UI.WebControls.Sublayout)Parent;
Guid dataSourceId;
if (Guid.TryParse(sublayout.DataSource, out dataSourceId))
{
_dataSource = Sitecore.Context.Database.GetItem(new ID(dataSourceId));
}
else
{
_dataSource = Sitecore.Context.Database.GetItem(sublayout.DataSource);
}
}
if (_dataSource == null)
{
_dataSource = Sitecore.Context.Item;
}
}
return _dataSource;
}
}

Related

new list show up in RecyclerView after item deleted

I got an issue when I tried to remove an item in a list. when I tried to remove a list it disappeared, but they show a new list. the case looks like this.
below I provided my code also
adapter.setOnItemClickedCallback(object : ListOrderAdapter.OnItemClickCallback {
override fun onDecrementButtonClicked(orderMenu: OrderMenu, itemView: View, position: Int) {
var quantityChanged = (orderMenu.quantity)!!.minus(1)
itemView.tv_order_number.text = quantityChanged.toString()
Log.e("Position", position.toString())
if (quantityChanged > 0) {
updateData(quantityChanged, orderMenu)
} else {
listItem.remove(orderMenu)
recyclerView.removeViewAt(position)
adapter.notifyItemRemoved(position)
adapter.notifyItemRangeRemoved(position, listItem.size)
Toast.makeText(applicationContext, "Pesanan telah di hapus dari orderan", Toast.LENGTH_SHORT).show()
}
}
})
}
private fun updateData(quantityChanged: Long, orderMenu: OrderMenu) {
for (item in listItem){
if (item.name.equals(orderMenu.name)){
item.quantity = quantityChanged
}
}
}

ListView item as a progress bar

I was wondering if someone can maybe help me with the following intent:
I created an app which simply displays a table. It shows a table head and beyond that a list view which contains several items.
Is it possible, that if one clicks on one of these items, a progress bar is shown which loads smoothely in a certain time interval (lets say 30 seconds) from left to right?
Please see my screenshot below, maybe it's easier to understand what I am trying to do:
Finally, I don't know if it helps, but let me attach some code as well. I shortened it a little, if something is missing for understanding (like the list class) or if I removed to much, please let me know:
public class TableActivity : Activity
{
ListView lv;
ListAdapter adapter = null;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
//...
lv = FindViewById<ListView>(Resource.Id.geraeteListView);
adapter = new ListAdapter(this, Resource.Layout.List, geraeteliste.CurrentGeraeteliste, Intent.GetStringExtra("ServerIP"))
{
parentActivity = this
};
lv.Adapter = adapter;
}
private async void OnItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
if (geraeteliste.CurrentGeraeteliste[e.Position].bespielt == "J") return;
//…
await Task.Delay(0);
}
}
public class ListAdapter : ArrayAdapter
{
//...
public override View GetView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
if (v == null)
{
LayoutInflater inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
v = inflater.Inflate(Resource.Layout.List, parent, false);
}
//...
v.FindViewById<ImageView>(Resource.Id.typeImageView).SetImageResource(Resource.Drawable.Icon);
v.FindViewById<TextView>(Resource.Id.numberTextView).Text = Geraetelist[position].geraeteplatz;
v.FindViewById<TextView>(Resource.Id.descriptionTextView).Text = Geraetelist[position].geraeteinformation;
ImageView iv = v.FindViewById<ImageView>(Resource.Id.bspImageView);
iv.SetImageResource(Geraetelist[position].bespielt == "N" ? Resource.Drawable.greenPoint : Resource.Drawable.redPoint);
//…
return v;
}
}
Can anyone maybe give me a short hint or something? How can I implement such a progress bar for every item on click?^^ Would be really happy for every helping effort.
Thanks in advance for every answer,
Best regards
Is it possible, that if one clicks on one of these items, a progress bar is shown which loads smoothly in a certain time interval (lets say 30 seconds) from left to right?
If you want to display progressbar when click Listview item, I do one sample for you, you can take a look:
1.Declare ListView layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" android:orientation="vertical">
<ListView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/ListView" />
</LinearLayout>
2.Declare list row layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ProgressBar android:id="#+id/progressBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" android:visibility="invisible"
style="#android:style/Widget.ProgressBar.Horizontal" />
</LinearLayout>
3.Define ListView Adapter
public class Post
{
public string title { get; set; }
public bool isselect { get; set; }
}
public class CusotmListAdapter : BaseAdapter<Post>
{
Activity context;
List<Post> list;
public CusotmListAdapter(Activity _context, List<Post> _list)
: base()
{
this.context = _context;
this.list = _list;
}
public override Post this[int position]
{
get { return list[position]; }
}
public override int Count
{
get { return list.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
// re-use an existing view, if one is available
// otherwise create a new one
if (view == null)
view = context.LayoutInflater.Inflate(Resource.Layout.ListItemRow, parent, false);
Post item = this[position];
view.FindViewById<TextView>(Resource.Id.textView1).Text = item.title;
if(item.isselect==true)
{
view.FindViewById<ProgressBar>(Resource.Id.progressBar1).Visibility = ViewStates.Visible;
}
else
{
view.FindViewById<ProgressBar>(Resource.Id.progressBar1).Visibility = ViewStates.Invisible;
}
return view;
}
}
4.Setting ListView Adapter
public class MainActivity : AppCompatActivity
{
private ListView listview;
List<Post> posts = new List<Post>();
private CusotmListAdapter adapter;
private int oldposition = -1;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
posts.Add(new Post() { title = "title 1", isselect = false });
posts.Add(new Post() { title = "title 2", isselect = false });
posts.Add(new Post() { title = "title 3", isselect = false });
posts.Add(new Post() { title = "title 4", isselect = false });
posts.Add(new Post() { title = "title 5", isselect = false });
posts.Add(new Post() { title = "title 6", isselect = false });
posts.Add(new Post() { title = "title 7", isselect = false });
posts.Add(new Post() { title = "title 8", isselect = false });
SetContentView(Resource.Layout.activity_main);
listview = FindViewById<ListView>(Resource.Id.ListView);
listview.ItemClick+= OnListItemClick;
adapter= new CusotmListAdapter(this, posts);
listview.Adapter = adapter;
}
private void OnListItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
if(oldposition!=-1)
{
Post p1 = adapter[oldposition];
p1.isselect = false;
}
oldposition = e.Position;
Post p = adapter[e.Position];
p.isselect = true;
adapter.NotifyDataSetChanged();
}
}
Update
You can change some code in CusotmListAdapter GetView event:
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
// re-use an existing view, if one is available
// otherwise create a new one
if (view == null)
view = context.LayoutInflater.Inflate(Resource.Layout.ListItemRow, parent, false);
Post item = this[position];
view.FindViewById<TextView>(Resource.Id.textView1).Text = item.title;
ProgressBar p = view.FindViewById<ProgressBar>(Resource.Id.progressBar1);
p.Max = 100;
p.Progress = 100;
//p.IncrementProgressBy(-10);
if(item.isselect==true)
{
view.FindViewById<ProgressBar>(Resource.Id.progressBar1).Visibility = ViewStates.Visible;
new Thread(new ThreadStart(delegate
{
while (p.Progress > 0)
{
p.Progress -= 20;
Thread.Sleep(1000);
}
})).Start();
}
else
{
view.FindViewById<ProgressBar>(Resource.Id.progressBar1).Visibility = ViewStates.Invisible;
}
return view;
}
Then please look at the screenshot:
It's clear that you are missing some knowledge on ListViews. This Xamarin university course has some examples and a video that explain the different components.
But basically, you can put your background progress bar as a View in your row AXML layout file, and depending on the value of the Progress property, that view can change widths.
Let me know if you have questions

Xamarin.Android: Changing a specific value in a list during runtime

I have a simple Xamarin.Android-App.
On the Activity of this app, there is a list displayed. Please see following MyActivity.axml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android ="http://schemas.android.com/apk/res/android"
android:orientation ="vertical"
android:layout_width ="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width ="match_parent"
android:layout_height="wrap_content"
android:text ="Click Me"
android:layout_marginTop ="20dp"
android:layout_marginLeft ="25dp"
android:layout_marginRight ="25dp"
android:id="#+id/button" />
<Space
android:layout_width="match_parent"
android:layout_height="25dp"
android:id="#+id/space" />
<ListView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/list" />
</LinearLayout>
One row of this list contains simply two entries, please see ListRow.axml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft ="5dp"
android:layout_marginTop ="10dp"
android:layout_marginBottom="10dp"
android:layout_marginRight ="5dp" />
<TextView
android:id="#+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft ="5dp"
android:layout_marginTop ="10dp"
android:layout_marginBottom="10dp"
android:layout_marginRight ="5dp" />
</RelativeLayout>
So the code-behind of that activity looks like the following:
public class MyActivity : Activity
{
List<Entry> List = null;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.MyActivity);
List = PopulateList();
var lv = FindViewById<ListView>(Resource.Id.list);
var adapter = new ListAdapter(this, Resource.Layout.List, List);
lv.Adapter = adapter;
FindViewById<Button>(Resource.Id.button).Click += OnButtonClick;
}
}
For the sake of completeness, here is the code for my ListAdapter.cs-class:
class ListAdapter : ArrayAdapter
{
List<Entry> List;
public ListAdapter(Context Context, int ListId, List<Entry> List) : base(Context, ListId, List)
{
this.List = List;
}
public override int Count
{
get { return List.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
if (v == null)
{
LayoutInflater inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
v = inflater.Inflate(Resource.Layout.List, parent, false);
}
v.FindViewById<TextView>(Resource.Id.name).Text = List[position].Name;
v.FindViewById<TextView>(Resource.Id.value).Text = "Original Value";
return v;
}
}
So my question now is the following: Assuming that there is more than one item within that List. On click of the button, I want to change one specific text within that list. Let's say of the second entry in the list the (Resource.Id.value).Text (which now says "Original Value") to "Changed Value" or something like that. But only of the second one. All the other items should stay the same.
Please see following example of output aimed, maybe it's easier to understand what I am trying to do:
Name Value
- - - - - - - - - - - - - - - -
No.1 Original Value
No.2 Original Value
No.3 Original Value
[Button Click]
Name Value
- - - - - - - - - - - - - - - -
No.1 Original Value
No.2 Changed Value
No.3 Original Value
Can anyone maybe help me / tell me how to do this? What does my private void OnButtonClick(object sender, EventArgs e)-method have to look like? How can I access a single entry in that list?
Thanks in advance for all answers and best regards
you could add a method in adapter to notifyDataSetChanged(); :
class ListAdapter : ArrayAdapter
{
List<Entry> List;
private int ItemPositionToChange = -1;
public ListAdapter(Context Context, int ListId, List<Entry> List) :
base(Context, ListId, List)
{
this.List = List;
}
//this method to let adapter notify
public void ChangeItemValue(int position)
{
ItemPositionToChange = position;
NotifyDataSetChanged();
}
public override int Count
{
get { return List.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
if (v == null)
{
LayoutInflater inflater =
(LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
v = inflater.Inflate(Resource.Layout.List, parent, false);
}
v.FindViewById<TextView>(Resource.Id.name).Text = List[position].Name;
//change the item value according to your needs
if(position == ItemPositionToChange ){
v.FindViewById<TextView>(Resource.Id.value).Text = "Changed Value";
}else{
v.FindViewById<TextView>(Resource.Id.value).Text = "Original Value";
}
return v;
}
}
then in your button click listener :
void OnButtonClick(object sender, EventArgs e)
{
//positionToChange is which item you want to change
adapter.ChangeItemValue(positionToChange);
}
I'm not too familiar with the Entry class, but it seems to have a Text property.
Assuming you know the index of the string (myIndex below):
private void OnButtonClick(object sender, EventArgs e) {
List[myIndex].Text = "Changed Value";
adapter.notifyDataSetChanged();
}

flex mobile - performance of spark List with ItemRenderers that has large image

I'm developing the spark List with Large Images in flex mobile.
Each ItemRenderer has a large image.
like this.
<s:ItemRenderer>
...
<s:BitmapImage source="{data.bmpData}" />
</s:ItemRenderer>
In dataProvider, there is BitmapData as name "bmpData".
The problem is performance while scrolling.
While scrolling, it stopped for a while when new Image is rendered.
help me please.
If the problem is you render too many bitmapdata in same time, you can render them one by one in different frames.
Here is an example.
Make a custom ItemRenderer
class YourItemRenderer
{
override public function set data(value:Object):void
{
if (super.data != value)
{
super.data = value;
yourBitmapImage.source = null;
//when the data change, don't call the render function directly
EnterFrameManager.getInstance().addRenderFunction(render)
}
}
private function render():void
{
if (yourBitmapImage != null && data != null)
{
yourBitmapImage.source = data.bmpData;
}
}
}
EnterFrameManager is used to control the render functions.
class EnterFrameManager
{
import mx.core.FlexGlobals;
public function EnterFrameManager()
{
FlexGlobals.topLevelApplication.addEventListener( Event.EnterFrame, onEnterFrameHandler)
}
private var _instance:EnterFrameManager;
public static function getInstance():EnterFrameManager
{
if (_instance == null)
{
_instance = new EnterFrameManager();
}
return instance;
}
//save the render functions
private var renderQueue:Array = [];
private var nowIntervalFrame:int = 0;
//change it to small value when you don't feel lag
private const UPDATE_INTERVAL_FRAMES:int = 6;
private function onEnterFrameHandler(e:Event):void
{
nowIntervalFrame++;
if (nowIntervalFrame >= UPDATE_INTERVAL_FRAMES)
{
nowIntervalFrame = 0;
//change renderQueue by waitQueue
for each (var f:Function in waitQueue)
{
addFunctionToQueue(f, renderQueue);
}
waitQueue.length = 0;
if (renderQueue.length > 0)
{
var f:Function = renderQueue.shift();
f();
}
}
}
private var waitQueue:Array = [];
public function addRenderFunction(f:Function):void
{
addFunctionToQueue(f, waitQueue);
}
private function addFunctionToQueue(f:Function, queue:Function):void
{
var index:int = queue.indexOf(f);
if (index == -1)
{
queue.push(f);
}
else
{
var temp:Function = queue.splice(index, 1);
queue.push(temp);
}
}
}

Sitecore Add Mutiple Language version to the same Item

How do i create a Field value for a Particular Item in a Particular Language? I have an Excel that has all the item Names inside the RootItem .These Items exist in a en-US language Already. i need add values for a particular field for other languages.. Like en-GB, nl-NL, it-IT.
I have a List like
ItemName Language Translation
TestItem en-GB Hello
TestItem nl-NL Hallo
and so on..
The only problem is, when i do item.Add, it creates a new item rather than adding the value to the existing item. How can i handle this?
My code is as follows:
foreach (DataRow row in dt.Rows)
{
Language language = Language.Parse(languageId);
var rootItem = currentDatabase.GetItem(RootItemPath, language);
var item = rootItem.Add(itemName, templateItem);
if (item != null)
{
item.Fields.ReadAll();
item.Editing.BeginEdit();
try
{
//Add values for the fields
item.Fields["Translation"].Value = strTranslationValue;
}
catch (Exception)
{
item.Editing.EndEdit();
}
}
}
Try This:
var rootItem = currentDatabase.GetItem(RootItemPath);
foreach (DataRow row in dt.Rows)
{
Language language = Language.Parse(languageId);
var itemInCurrentLanguage = rootItem.Children.Where(i=>i.Name == itemName).FirstOrDefault();
if(itemInCurrentLanguage == null){
itemInCurrentLanguage = rootItem.Add(itemName, templateItem);
}
var itemInDestinationLanguage = currentDatabase.GetItem(itemInCurrentLanguage.ID, language );
if (itemInDestinationLanguage != null)
{
itemInDestinationLanguage.Fields.ReadAll();
itemInDestinationLanguage.Editing.BeginEdit();
try
{
//Add values for the fields
itemInDestinationLanguage.Fields["Translation"].Value = strTranslationValue;
}
catch (Exception)
{
//Log any error
}
finally
{
itemInDestinationLanguage.Editing.EndEdit();
}
}
}
You need to switch the language before you get the root item:
using (new LanguageSwitcher(language))
{
var rootItem = currentDatabase.GetItem(RootItemPath);
var item = rootItem.Add(selectedItem.Name, CommunityProjectTemplateId);
// Add new item here...
}