How to recover the ID of a Picker in Xamarin - c#

You have a Picker in Xamarin that displays the name of certain Fabricantes, as follows
this picker is filled by passing an ObservableCollection of the FABRICANTES object
Fabricantes.CS:
public class Fabricante
{
[JsonProperty(PropertyName = "id")]
public int Id { get; set; }
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
}
FiltrosView.XAML:
<Picker Title="Seleccione Fabricante"
Margin="15,5,15,5"
HorizontalOptions="FillAndExpand"
ItemsSource="{Binding Fabricantes, Mode=TwoWay}"
ItemDisplayBinding="{Binding Name}"
SelectedItem="{Binding Id}"
SelectedIndex="{Binding Id}">
</Picker>
How do I fill the Picker?
Here I declare the list and the property that will capture the ID of the picker, to open the list in the picker, I will cast the object that arrives from an API and will fill the Observable collection and then bindarla in sight, it WORKS!
FiltrosViewModel.CS:
public ObservableCollection<Fabricante> Fabricantes { get; set; }
public int IdSustancia
{
get
{
return idSustancia;
}
set
{
if (idSustancia != value)
{
idSustancia = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IdSustancia)));
}
}
}
var response = await apiService.GetList<Fabricante>(urlService, param);
var list = (List<Fabricante>)response.Result;
Fabricantes.Clear();
foreach (var item in list)
{
Fabricantes.Add(item);
}
But, since I capture the ID (int) of the value that the user entered (string), can this be done in xamarin?
I would like to be able to capture the value of the ID of the picker in the property IdSubstance declared previously, how to do it? any help for me?

The best way of doing that is binding the selected index of the picker. In your XAML code, add the following line to your picker:
SelectedIndex={Binding IdSustancia, Mode=TwoWay}
So, when index != -1 (initial value), you can get Fabricante's ID in your ObservableCollection, accessing Fabricantes[IdSustancia].

use the SelectedItem property
SelectedItem="{Binding IdSustancia}"
however, for this to work you need to bind it to a property of type Fabricante.

Related

How to assign a List of Booleans to a generated Checkbox IsChecked property in WPF?

I've recently started learning C# and I've encountered a problem. I display a set of keywords in a generated checkbox in my WPF and I want to check the element (IsChecked) based on an input check from a TXT file.
If the currently selected element from a different listbox matches the read modelclass(from a txt file) then set the checked key true.
I'm generating a Checkbox in my WPF to list a set of keywords that my app reads from a txt file.
The txt file contains the following items per line:
-id
-key
-pair
-description
WPF code:
<ListView ItemsSource="{Binding XAMLModelKeywords}" SelectedItem="{Binding XAMLModelKeyword}" Margin="5" x:Name="listofallkeys" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" >
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding XAMLAssignedKeys}" Content="{Binding Key}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C#:
public ModelTemplates XAMLModelTemplate { get; set; }
public ModelKeywords XAMLModelKeyword { get; set; }
public List<bool> XAMLAssignedKeys { get; set; }
public string XAMLKeyword { get; set; }
public ViewModelMain()
{
//This creates a new instance of ObservableCollection above
XAMLModelTemplates = new ObservableCollection<ModelTemplates>();
XAMLModelKeywords = new ObservableCollection<ModelKeywords>();
XAMLAssignedKeys = new List<bool>();
Refresh();
}
public void Refresh()
{
XAMLModelTemplates.Clear();
foreach (ModelTemplates tpl in ReadInput.ReadTemplateDirectory(Path))
{
XAMLModelTemplates.Add(tpl);
}
//Selecting the first item from the returned list
XAMLModelTemplate = XAMLModelTemplates.FirstOrDefault();
XAMLModelKeywords.Clear();
foreach (ModelKeywords tpl in ReadInput.ReadKeywordsFile(KeyWordsPath))
{
XAMLModelKeywords.Add(tpl);
}
XAMLModelKeyword = XAMLModelKeywords.FirstOrDefault();
XAMLAssignedKeys.Clear();
foreach (ModelKeywords tpl in XAMLModelKeywords)
{
XAMLAssignedKeys.Add(ReadInput.CheckPairedtemplates(tpl, XAMLModelTemplate));
}
ModelKeyword:
public class ModelKeywords
{
public int Id { get; set; }
public string Key { get; set; }
public List<string> PairedTemplates { get; set; }
public string Description { get; set; }
}
ModelTemplate:
public class ModelTemplates
{
//path to a template
public int Id { get; set; }
public string TemplatePath { get; set; }
public string TemplateName { get; set; }
public ExcelRange TemplateRange { get; set; }
}
ReadKeywordsFile:
Returns a list of Template Models (name of template file, path) and the displays it in a listbox.
ReadKeywordsFile:
Returns a list of Keywords Model (id, key, pair, desc) and then displays it in a generated listbox.
CheckPairedtemplates:
Returns a list of booleans based on the currently selected Template Model matches the Keywords Model pair (list of string).
TLDR:
I have a list of booleans ( XAMLAssignedKeys) and I want to match it to my generated checkbox in WPF, however the generation happens based on an item template and I'm not sure how to link one element from my list of booleans to the checkbox "IsChecked" property.
ScreenshotofApp
Thank you much in advance for the advices.
Since you set ObservableCollection<ModelKeywords> (XAMLModelKeywords) to ItemsSource property of ListView (listofallkeys), each item of the ListView will be bound to a member of the ObservableCollection. In this case, the CheckBox inside DataTemplate will be bound to a ModelKeywords in XAMLModelKeywords. Therefore, you need to bind the properties of CheckBox with the properties of ModelKeywords.
In the Xaml, you mistakenly set XAMLAssignedKeys to IsChecked property of CheckBox. It must be a property of ModelKeywords. The remedy will be to add a bool property to ModelKeywords, somehow copy a value in the XAMLAssignedKeys to the property, and then bind the property with IsChecked properties of CheckBox.
Let's say, if you add IsEnabled bool property to ModelKeywords, the Xaml will be
<CheckBox IsChecked="{Binding IsEnabled}" Content="{Binding Key}"/>
In addition, unless you implement INotifyPropertyChanged interface to ModelKeywords, only initial value of the property will be sent to the CheckBox and the subsequent values will not be notified and reflected to the CheckBox when the property is changed.

Synchronizing two comboboxes bound to the same collection and to the same selected item

I have two comboboxes to represent a customer code and a customer name. Both are bound to the same collection of objects and to the same SelectedItem. I want to update the customer name when I select a customer code and vice versa.
I am using C# with the MVVM pattern. I have tried all the combination of SelectedItem and SelectedValue with selectedvaluepath but nothing seems to work.
These are my two combo boxes:
<ComboBox Name="CmbStockUnitCustomerCode" ItemsSource="{Binding CustomerCodeDtos}"
DisplayMemberPath="Code" SelectedItem="{Binding SelectedCustomer, Mode=TwoWay}"
IsSynchronizedWithCurrentItem="True"></ComboBox>
<ComboBox Name="CmbStockUnitCustomerName" ItemsSource="{Binding CustomerCodeDtos}"
DisplayMemberPath="Name" SelectedItem="{Binding SelectedCustomer, Mode=TwoWay}"
IsSynchronizedWithCurrentItem="True"></ComboBox>
And these are the bound objects:
public CustomerDto SelectedCustomer
{
get => _selectedcustomer;
set
{
_selectedcustomer = value;
RaisePropertyChanged("SelectedCustomer");
}
}
public class CustomerDto
{
public short Code { get; set; }
public string Name { get; set; }
public CustomerDto(short code, string name)
{
this.Code = code;
this.Name = name;
}
}
public ObservableCollection<CustomerDto> CustomerCodeDtos
{
get => _databaseService.GetAllCustomers();
}
When I update one of the comboboxes, I expect the other one to update to the corresponding value in the object CustomerDto, but nothing happens.
You're recreating your collection every time you reference it, so SelectedItem is referencing a different object. In effect, your two combo boxes are using different collections as ItemsSources. Change the code to
public ObservableCollection<CustomerDto> CustomerCodeDtos
{
get
{
if(_customerCodes==null)
{
_customerCodes = _databaseService.GetAllCustomers();
}
return _customerCodes;
}
}

Get SelectedItem of ComboBox Bound Multi-Colum List

I have a multi-column List bound to a ComboBox.
It displays List Column Name as the ItemSource.
Problem
SelectedItem does return the Name.
With MessageBox.Show(vm.cboVideoQuality_SelectedItem); the string shows as MyProgram.ViewModel+VideoQuality instead of High.
I tried filtering Name with:
vm.cboVideoQuality_SelectedItem.FirstOrDefault(s => s.Name);
But it gives error 'char' does not contain definition for Name.
XAML
Bind Item Source and Selected Item.
<ComboBox x:Name="cboVideoQuality"
ItemsSource="{Binding cboVideoQuality_Items, Mode=TwoWay}"
DisplayMemberPath="Name"
SelectedItem="{Binding cboVideoQuality_SelectedItem, Mode=TwoWay}"
SelectedValuePath="Name"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="0,0,0,0"
Width="100" />
ViewModel
// Item Source
//
public class VideoQuality
{
public string Name { get; set; }
public string Bitrate { get; set; }
}
public List<VideoQuality> _cboVideoQuality_Items = new List<VideoQuality>()
{
new ViewModel.VideoQuality() { Name = "High", Bitrate = "5000K" },
new ViewModel.VideoQuality() { Name = "Medium", Bitrate = "2500K" },
new ViewModel.VideoQuality() { Name = "Low", Bitrate = "500K" },
};
public List<VideoQuality> cboVideoQuality_Items
{
get { return _cboVideoQuality_Items; }
set
{
_cboVideoQuality_Items = value;
OnPropertyChanged("cboVideoQuality_Items");
}
}
// Selected Item
//
public string _cboVideoQuality_SelectedItem { get; set; }
public string cboVideoQuality_SelectedItem
{
get { return _cboVideoQuality_SelectedItem; }
set
{
if (_cboVideoQuality_SelectedItem == value)
{
return;
}
_cboVideoQuality_SelectedItem = value;
OnPropertyChanged("cboVideoQuality_SelectedItem");
}
}
C#
I cannot check if selected = "High" because SelectedItem does not equal Name.
It equals MyProgram.ViewModel+VideoQuality.
ViewModel vm = mainwindow.DataContext as ViewModel;
string selected = vm.cboVideoQuality_SelectedItem;
if (selected == "High")
{
// ...
}
You have already used SelectedValuePath and should of course also use SelectedValue instead of SelectedItem:
<ComboBox
ItemsSource="{Binding cboVideoQuality_Items}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding cboVideoQuality_SelectedItem}" .../>
As a note, in both Bindings Mode=TwoWay is redundant. An ItemsSource binding is never two-way, while a SelectedValue binding is two-way by default.
I'd also recommend not to use binding target property details in view model property names. E.g. cboVideoQuality_SelectedItem should just be SelectedVideoQuality. Thus you may also bind it to the SelectedValue property of a ListBox or even the Text property of a TextBlock without too much confusion.

WPF Combobox display only SOME items

So I have a WPF app(with MVVM) and in this I have a combobox which binds to a table in my database and displays the values, this works just fine.
However, now I want to make a new combobox and bind it to the same table, but now I only want it to display SOME of the values. Is there a simple way to do this?
The table has has four entries but I only want to show 3 of them in this new combobox.
I know I could just make a new table in the database to bind to, but I might have to use several of these comboboxes(with different values) and I'd rather not go through all that bother if I can avoid it.
XAML:
<ComboBox
Name="cmComp"
MinWidth="150"
Margin="12 0 0 12"
ItemsSource="{Binding SelectedComponentLookup}"
DisplayMemberPath="ComponentChoice"
SelectedValuePath="ComponentChoice"
SelectedItem="{Binding ComponentChosen}">
</ComboBox>
VIEWMODEL:
private IEnumerable<ComponentLookupDto> _selectedComponentLookup;
public IEnumerable<ComponentLookupDto> SelectedComponentLookup
{
get { return _selectedComponentLookup; }
set
{
_selectedComponentLookup = value;
}
}
DTO:
public class ComponentLookupDto
{
public int ComponentLookupId { get; set; }
public string ComponentChoice { get; set; }
}
The way I achieve this is that I filter out the items I don't want to display in the getter for the property to which I bind my ItemsSource. :
XAML:
<ComboBox ItemsSource={Binding SelectedComponentLookupOther} ... />
And in your ViewModel:
public IEnumerable<ComponentLookupDto> SelectedComponentLookupOther
{
get { return _selectedComponentLookup.Where(c => c.SomeProperty == "however you want to pick it out"); }
}

WPF ComboBox Selected Item with reference to an object

I'm trying to define a selected item in a combobox. It working fine if I'm just using a String to declare the selected item but not if using an object.
<ComboBox HorizontalAlignment="Left"
VerticalAlignment="Top" Width="81" materialDesign:HintAssist.Hint="Woche" Margin="10"
ItemsSource="{Binding weekSelection}"
DisplayMemberPath="name"
SelectedItem="{Binding nodeWeek, Mode=TwoWay}"
SelectedValue="name" />
-
private week _nodeWeek;
public week nodeWeek
{
get
{
return _nodeWeek;
}
set
{
_nodeWeek = value;
RaisePropertyChanged("nodeWeek");
}
}
-
public class week
{
public int val { get; set; }
public String name { get; set; }
}
-
setting the selected item
this.nodeWeek = new week() { val = times.GetIso8601WeekOfYear(DateTime.Now), name = "KW " + times.GetIso8601WeekOfYear(DateTime.Now).ToString() };
Is there a way to fix that?
The selected item must be always one of the list of your items source. You cannot create new objects and assign them to the SelectedItem. The Combobox simply compares object references not the content.

Categories

Resources