Selecting TextCell by code doesn't highlight row - c#

When I click a TextCell in a ListView, the row is highlighted.
However, when I programatically select a row / a TextCell, the row isn't highlighted.
Therefore it isn't possible to indicate to the user which value in a ListView is currently selected unless he changes the selection by tapping a row.
Is that a bug or a missing feature, or how could I achieve the highlighting via code?
Sample code is attached below.
using MyApp.Model;
using System.Collections.Generic;
using Xamarin.Forms;
namespace MyApp
{
public class IntSelector : ContentPage
{
private ListView m_ListView;
public IntSelector(int uSelectedInt)
{
DataTemplate nTemplate = new DataTemplate(typeof(TextCell));
// We can set data bindings to our supplied objects.
nTemplate.SetBinding(TextCell.TextProperty, "String");
nTemplate.SetBinding(TextCell.DetailProperty, "Int");
List<clsStringInt> nList = new List<clsStringInt>();
clsStringInt nItem1 = new clsStringInt { String = "German", Int = 1031 };
clsStringInt nItem2 = new clsStringInt { String = "English", Int = 1033 };
clsStringInt nItem3 = new clsStringInt { String = "Spanish", Int = 1034 };
nList.Add(nItem1);
nList.Add(nItem2);
nList.Add(nItem3);
m_ListView = new ListView();
m_ListView.ItemTemplate = nTemplate;
m_ListView.ItemsSource = nList;
m_ListView.ItemSelected += this.OnSelection;
m_ListView.SelectedItem = nItem2;//this triggers the "OnSelection" event, so it works
nItem2.String = "->> " + nItem2.String; //the item's new string is display in the ListView, so that works as well
//what DOESN'T work is the highliting
this.Content = m_ListView;
}
void OnSelection(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null)
{
return; //ItemSelected is called on deselection, which results in SelectedItem being set to null
}
clsStringInt n = (clsStringInt)e.SelectedItem;
string sSelectedIntAsString = n.Int.ToString();
DisplayAlert("Item Selected", sSelectedIntAsString, "Ok");
}
}
}
namespace MyApp.Model
{
public class clsStringInt
{
public string String { get; set; }
public int Int { get; set; }
}
}

As mentioned in the comments you are testing on a UWP Forms app which this appears to be a bug specifically on that platform seeing how it works fine on Android and iOS.
I was able to work around this by setting the selected item in OnAppearing instead of in the Page constructor to get it to highlight.

Related

My code-generated ListBox's items isn't showing any content

I have a code-generated window in WPF, (using dotnet core 3.0 preview 6), and when running my application gets the correct data, and the ListBox is populated with the correct number of rows, but none of them contains values
This is a test-project I'm doing to get familiar with code generated WPF as it's needed for an upcoming project we're doing at work; I would have preferred using XAML but my lead says that that will create issues with code-re-usability.
I at first made sure I used am object which is "clean", (my entities are setup for Linq2db, so I ensured that the attributes couldn't be the culprit), then I tested binding, (just got the "Error 40" -error code, but that isn't relevant to the main problem). I have also changed the type of boxes, but It does not help, (DataGrid did work but it's not what I'm looking for in a visual).
public class ChatWindow : IChatWindow
{
private ObservableCollection<MessageDto> _observableMessages;
private readonly IMessagesRepository _messagesRepository;
public ChatWindow(IMessagesRepository messagesRepository)
{
_messagesRepository = messagesRepository;
Task.Run(async () => { await Updater(); }).ConfigureAwait(false);
}
public async Task ShowAsync(User user)
{
var chatLog = new ListBox()
{
Name = "Chatview",
ItemsSource = _observableMessages,
ItemTemplate = new DataTemplate(typeof(MessageDto)),
DataContext = _observableMessages
};
//var myBinding = new Binding("_observableMessages");
//myBinding.Source = _observableMessages;
//chatLog.SetBinding(ListBox.ItemsSourceProperty, myBinding);
var input = new TextBox()
{
Name = "InputField",
Background = new SolidColorBrush(Color.FromRgb(35, 35, 35))
};
var stackPanel = new StackPanel()
{
Children =
{
chatLog,
input
}
};
var window = new Window()
{
Name = "ChatWindow",
Content = stackPanel,
};
window.Show();
}
private async Task Updater()
{
while (true)
{
var messages = await _messagesRepository.GetAllMessages(1);
_observableMessages = new ObservableCollection<MessageDto>(messages.Select(m => new MessageDto()
{
Timestamp = m.Timestamp,
From = m.From,
Message = m.Message
}));
await Task.Delay(TimeSpan.FromSeconds(10));
}
}
}
class MessageDto
{
public DateTime Timestamp { get; set; }
public long From { get; set; }
public string Message { get; set; }
}
Image of the resultant window, (some styling code was removed from the example code to reduce noise)
Based on Flithor's comment, i did this and it worked perfectly:
private DataTemplate GetDataTemplate()
{
var dataTemplate = new DataTemplate(typeof(MessageDto));
FrameworkElementFactory stackPanelFactory = new FrameworkElementFactory(typeof(StackPanel));
stackPanelFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
FrameworkElementFactory timestamp = new FrameworkElementFactory(typeof(Label));
timestamp.SetBinding(Label.ContentProperty, new Binding("Timestamp"));
FrameworkElementFactory from = new FrameworkElementFactory(typeof(Label));
from.SetBinding(Label.ContentProperty, new Binding("From"));
FrameworkElementFactory message = new FrameworkElementFactory(typeof(Label));
message.SetBinding(Label.ContentProperty, new Binding("Message"));
stackPanelFactory.AppendChild(timestamp);
stackPanelFactory.AppendChild(from);
stackPanelFactory.AppendChild(message);
dataTemplate.VisualTree = stackPanelFactory;
return dataTemplate;
}

C# Reading from multiple text files, splitting lines into a List, and then loading into ListBox

I'm getting a few errors and also my code is unfinished. I was using another Stackoverflow question to set this up to begin with but it wasn't fit to my needs.
I have three text files which the data is split by commas such as "Name,25,25.6" so string, int, decimal. I have all three text files that have three columns like that, same data types, but just different names/numbers.
I have three different list boxes that I want to split them into but I'm having trouble getting the three different split list items to get into three different list boxes. I'll copy and paste all the code I have. I am also using a combo box to allow the user to select the file they want to load into the combo box which I believe I got it right.
The errors I get are in the displayLists(), it says on the lstItemName.DataSource = Inventory; line that Inventory does not exist in the current context. There are also a plenitude of other errors.
Any help will be appreciated, I'll copy and paste my code. I have a Windows Form and I'm using Visual Studio Express 2012 in C#
namespace TCSCapstone
{
public partial class frmInventory : Form
{
public frmInventory()
{
InitializeComponent();
}
string cstrItemName;
int cintNumberOfItems;
decimal cdecPrice;
decimal cdecTotalPrices;
string selectedList = "";
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
selectedList = this.cmbList.GetItemText(this.cmbList.SelectedItem);
if (selectedList == "Creative Construction")//if the selected combo
box item equals the exact string selected
{
selectedList = "creative"; //then the string equals creative,
which is creative.txt but I add the .txt in the btnLoadInfo method
} else if (selectedList == "Paradise Building")
{
selectedList = "paradise";//this is for paradise.txt
}
else if (selectedList == "Sitler Construction")
{
selectedList = "sitler";//this is for sitler.txt
}
else
{
MessageBox.Show("Please select one of the items.");
}
}
private void btnLoadInfo_Click(object sender, EventArgs e)
{
List<frmInventory> Inventory = new List<frmInventory>();
using (StreamReader invReader = new StreamReader(selectedList +
".txt"))
{
while (invReader.Peek() >= 0)
{
string str;
string[] strArray;
str = invReader.ReadLine();
strArray = str.Split(',');
frmInventory currentItem = new frmInventory();
currentItem.cstrItemName = strArray[0];
currentItem.cintNumberOfItems = int.Parse(strArray[1]);
currentItem.cdecPrice = decimal.Parse(strArray[2]);
Inventory.Add(currentItem);
}
}
displayLists();
}//end of btnLoadInfo
void displayLists()
{
int i;
lstItemName.Items.Clear();
lstNumberOfItems.Items.Clear();
lstPrice.Items.Clear();
lstTotalPrices.Items.Clear();
lstItemName.DataSource = Inventory;
lstItemName.ValueMember = "cstrItemName";
lstItemName.DisplayMember = "cintNumberOfItems";
}
}//end of frmInventory
}//end of namespace
I do not know if this is exactly what you need, but try something like this:
public partial class Form2 : Form
{
List<Inventory> inventory;
public Form2()
{
InitializeComponent();
}
public void ReadFiles()
{
if (inventory == null)
inventory = new List<Inventory>();
using (TextReader r = new StreamReader("file.txt"))
{
string line = null;
while ((line = r.ReadLine()) != null)
{
string[] fields = line.Split(',');
Inventory obj = new Inventory();
obj.Name = fields[0];
obj.Qtd = Convert.ToInt32(fields[1]);
obj.Price = Convert.ToInt32(fields[2]);
inventory.Add(obj);
}
}
SetDataSourceList();
}
public void SetDataSourceList()
{
listBox1.DisplayMember = "Name";
listBox2.DisplayMember = "Qtd";
listBox3.DisplayMember = "Price";
listBox1.DataSource =
listBox2.DataSource =
listBox3.DataSource =
inventory;
}
}
public class Inventory
{
public string Name { get; set; }
public int Qtd { get; set; }
public decimal Price { get; set; }
}

Append a Row to a Datagrid in WPF using MVVM

I have a DataGrid in my View as shown below.,
My Question is how can I Append the values from the textboxes to the row datagrid
I have make sure that the Model has All the properties, When I click on the Add button it overwrites the dataGrid and shows only one latest record the and my ViewModel look like this:
class BatchItemsViewModel : ViewModelBase
{
public SearchItemsModel msearchItems { get; set; }
ObservableCollection<SearchItemsModel> _BatchItemsGrid;
public ObservableCollection<SearchItemsModel> BatchItemsGrid
{
get { return _BatchItemsGrid; }
set
{
_BatchItemsGrid = value;
OnPropertyChanged("BatchItemsGrid");
}
}
private ICommand _addDataToBatchGrid;
public ICommand addDataToBatchGrid
{
get
{
return _addDataToBatchGrid;
}
set
{
_addDataToBatchGrid = value;
}
}
public BatchItemsViewModel()
{
msearchItems = new SearchItemsModel();
addDataToBatchGrid = new RelayCommand(new Action<object>(AddDataInBatchGrid));
}
public void AddDataInBatchGrid(object obj)
{
ObservableCollection<SearchItemsModel> batchGridData = new ObservableCollection<SearchItemsModel>();
var data = new SearchItemsModel
{
BatchNumber = msearchItems.BatchNumber,
MFDDate = msearchItems.MFDDate,
ExpiryDate = msearchItems.ExpiryDate,
Quantity = msearchItems.Quantity,
};
batchGridData.Add(data);
BatchItemsGrid = batchGridData; // HERE I am overwriting the datagrid
//How can I Append the batchGridData to BatchItemsGrid (BatchItemsGrid.Append(batchGridData)???)
}
}
NOTE: I have gone through the other threads as well in the community for the similar posts but I couldn't find the appropriate and please correct me if I am going in wrong direction.
public void AddDataInBatchGrid(object obj)
{
var data = new SearchItemsModel
{
BatchNumber = msearchItems.BatchNumber,
MFDDate = msearchItems.MFDDate,
ExpiryDate = msearchItems.ExpiryDate,
Quantity = msearchItems.Quantity,
};
this.BatchItemsGrid.Add(data);
}
...Should do the trick. (don't replace the whole collection, just add items to it and let the notification events handle the UI updates)

Expandable ListView in Xamarin Forms

I have the following code to display a ListView using Xamarin Forms:
App.cs
public App ()
{
MainPage = GetMainPage();
}
public static Page GetMainPage()
{
return new NavigationPage(new DrilldownListViewByItem());
}
DrilldownListViewByItem:
public class DrilldownListViewByItem : ContentPage
{
public DrilldownListViewByItem()
{
Title = "Drilldown List Using ListView";
var listView = new ListView();
listView.ItemsSource = new ListItem[] {
new ListItem {Title = "First", Description="1st item"},
new ListItem {Title = "Second", Description="2nd item"},
new ListItem {Title = "Third", Description="3rd item"}
};
listView.ItemTemplate = new DataTemplate(typeof(TextCell));
listView.ItemTemplate.SetBinding(TextCell.TextProperty, "Title");
listView.ItemTapped += async (sender, args) =>
{
var item = args.Item as ListItem;
//if (item == null) return;
//await Navigation.PushAsync(new DetailPage(item));
//listView.SelectedItem = null;
};
Content = listView;
}
}
ListItem has these properties:
public string Title { get; set; }
public string Description { get; set; }
What I want to do is to show subitems when I tab on one of the main items. These subitems should be hidden at the beggining, but they should be there, I don't want to load them every time I tab on an item. Any idea? Thanks!
Try changing the visibility of the items you want to appear and disappear based on the click event of the list item.
On iOS you may also have to change the cell height (using HeightRequest), because it is likely that it won't change on it's own. I am guessing that android will work just fine.
Hope this helps.

c# windows 8 selected comboboxitem

I'm developping a Windows 8 Store Application (c#).
I have a Combobox (cboTeam1) that gets the items from a repository.
private static List<TeamItem> JPLItems = new List<TeamItem>();
public static List<TeamItem> getJPLItems()
{
if (JPLItems.Count == 0)
{
JPLItems.Add(new TeamItem() { Id = 1, Description = "Anderlecht", Image = "Jpl/Anderlecht.png", ItemType = ItemType.JPL });
JPLItems.Add(new TeamItem() { Id = 1, Description = "Beerschot", Image = "Jpl/Beerschot.png", ItemType = ItemType.JPL });
JPLItems.Add(new TeamItem() { Id = 1, Description = "Cercle Brugge", Image = "Jpl/Cercle.png", ItemType = ItemType.JPL });
JPLItems.Add(new TeamItem() { Id = 1, Description = "Charleroi", Image = "Jpl/Charleroi.png", ItemType = ItemType.JPL });
}
return JPLItems;
}
I load the items in the cboTeam1's ItemsSource:
cboTeam1.ItemsSource = ItemRepository.getJPLItems();
When cboTeam1 selectionchanged I do this:
private void cboTeam1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Ploeg1.Text = cboTeam1.SelectedValue.ToString();
}
This results in: SportsBetting.Model.TeamItem
Can anyone help me to get the combobox selectedvalue in my textblock (Ploeg1.Text)??
You've nearly answered this for yourself.
private void cboTeam1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// cast the selected item to the correct type.
var selected = cboTeam.SelectedValue as TeamItem;
//then access the appropriate property on the object, in this case "Description"
// note that checking for null would be a good idea, too.
Ploeg1.Text = selected.Description;
}
The other option would be to override ToString() in your TeamItem class to return Description. In that case your original code should work fine.
public override string ToString()
{
return this._description; // assumes you have a backing store of this name
}

Categories