I have an UWP app and I am using a RadDataGrid to show some data. When I do a API call to my API to set data in the grid, the data grid shows empty rows.
My XAML
<tg:RadDataGrid Grid.Row="2" UserGroupMode="Disabled" ColumnDataOperationsMode="Flyout" x:Name="infoGrid" ItemsSource="{x:Bind Path=ViewModel.history}" AutoGenerateColumns="False" FontSize="24" VerticalContentAlignment="Top" Margin="0,0,0,50" VerticalAlignment="Top" MaxHeight="500">
<tg:RadDataGrid.Columns>
<tg:DataGridTextColumn PropertyName="UpdatedBy" Header="Verplaatst door"/>
<tg:DataGridDateColumn PropertyName="UpdateDate" Header="Bijgewerkt op" CellContentFormat=" {0:dd/MM/yyyy}" />
<tg:DataGridTextColumn PropertyName="Location" Header="Verplaatst naar"/>
</tg:RadDataGrid.Columns>
</tg:RadDataGrid>
My C# code to set data
public async void APICALL()
{
var result = await LotService.GetLotInfo(ViewModel.scanField);
ViewModel.lot = result;
ViewModel.history = result.LotHistory;
infoGrid.ItemsSource = null;
infoGrid.ItemsSource = ViewModel.history;
IsBusy = false;
}
}
ViewModel.history is a List of LotHistoryInfo Class
EDIT: Added getters and setters as mm8 suggested
public class LotHistoryInfo
{
public LotInfo lot { get; set; }
public string scanField { get; set; }
public List<LotHistoryInfo> history { get; set; }
public LotHistoryInfo(LotStoreHistory his)
{
Location = new Location(his.LshStoreid.ToString(), his.LshStorex, his.LshStorey, his.LshStorez);
UpdatedBy = his.UpdatedBy;
UpdateDate = his.Updated;
}
public LotHistoryInfo()
{
}
}
My data grid acknowledges there should be 3 items in it, but it doesnt fill them in.
Sooo, what am I missing?
You can only bind to public properties:
public class LotHistoryInfo
{
public Location Location { get; set; }
public string UpdatedBy { get; set; }
public DateTimeOffset UpdateDate { get; set; }
public LotHistoryInfo(LotStoreHistory his)
{
Location = new Location(his.LshStoreid.ToString(), his.LshStorex, his.LshStorey, his.LshStorez);
UpdatedBy = his.UpdatedBy;
UpdateDate = his.Updated;
}
public LotHistoryInfo()
{
}
}
You have implemented Location, UpdatedBy and UpdateDate as fields:
public Location Location;
public string UpdatedBy;
public DateTimeOffset UpdateDate;
Related
I have two entities: Client and Manager.
Code for them is:
public partial class Manager
{
public Manager()
{
this.Clients = new HashSet<Client>();
}
public int Id_manager { get; set; }
public string Name_manag { get; set; }
public virtual ICollection<Client> Clients { get; set; }
}
public partial class Client
{
public Client()
{}
public int Id_cl { get; set; }
public int Manager { get; set; }
public virtual Manager Manager1 { get; set; }
}
ViewModel class has this code:
private ObservableCollection<Manager> _managerList;
public ObservableCollection<Manager> ManagerList
{
get { return _managerList; }
set
{
_managerList = value;
OnPropertyChanged("ManagerList");
}
}
On my view i have combobox, where i can choose a client manager.
Also i have a DataGrid, which shows the list of clients.
I binded ComboBox with this XML code:
<ComboBox Name="cbManager"
Margin="5"
Padding="3"
ItemsSource="{Binding ManagerList}"
DisplayMemberPath="Name_manag"
SelectedValuePath="Id_manager"
SelectedValue="Binding Manager1.Id_manager"
SelectedItem="{Binding Path=Manager1, Mode=TwoWay}"/>
So the problem is - when i open my view, i get an exception :
System.Windows.Markup.XamlParseException:
System.Number.StringToNumber(string, System.Globalization.NumberStyles, ref System.Number.NumberBuffer, System.Globalization.NumberFormatInfo, bool)
System.Number.ParseInt32(string, System.Globalization.NumberStyles, System.Globalization.NumberFormatInfo)
string.System.IConvertible.ToInt32(System.IFormatProvider)
System.Convert.ChangeType(object, System.Type, System.IFormatProvider)
MS.Internal.Data.SystemConvertConverter.Convert(object, System.Type, object, System.Globalization.CultureInfo)
MS.Internal.Data.DynamicValueConverter.Convert(object, System.Type, object, System.Globalization.CultureInfo)
System.Windows.Controls.Primitives.Selector.VerifyEqual(object, System.Type, object, MS.Internal.Data.DynamicValueConverter)
System.Windows.Controls.Primitives.Selector.FindItemWithValue(object, out int)
System.Windows.Controls.Primitives.Selector.SelectItemWithValue(object, bool)
System.Windows.Controls.Primitives.Selector.OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs)
I binded my ComboBox incorrectly, so help me to write correct bind.
I am fairly new to xaml and C# data bindings. I am attempting to bind a Picker to an IList using ItemsSource, ItemDisplayBinding, and SelectedItem. The Picker binds to the IList, but it doesn't display the correct information.
I've looked at several resources, and the Monkey App picker was a pretty big help. https://github.com/xamarin/xamarin-forms-samples/tree/master/UserInterface/MonkeyAppPicker
I tried replicating what he had done, but to no avail.
<Picker ItemsSource="{Binding Mills}"
ItemDisplayBinding="{Binding Name}"
SelectedItem="{Binding SelectedMill, Mode=TwoWay}"/>
namespace TDSDesktop
{
public class PurchaseAgreementBindings : INotifyPropertyChanged
{
public class Mill
{
public string Name { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Phone { get; set; }
}
public static class MillData
{
public static IList<Mill> Mills { get; private set; }
static MillData()
{
Mills = new List<Mill>();
Mills.Add(new Mill
{
Name = "Name1",
Address1 = "123",
Address2 = "City, State Zip",
Phone = "555-555-5555"
});
Mills.Add(new Mill
{
Name = "Name2",
Address1 = "456",
Address2 = "City, State Zip",
Phone = "888-888-8888"
});
}
}
public IList<Mill> Mills { get { return MillData.Mills; } }
Mill selectedMill;
public Mill SelectedMill
{
get { return selectedMill; }
set
{
if (selectedMill != value)
{
selectedMill = value;
OnPropertyChanged();
}
}
}
}
}
Theoretically, the picker should display two values (Name1 and Name2) because I have the ItemDisplayBinding set to Name. However, when I run my program, the values are "TDSDesktop.PurchaseAgreementBindings+Mill" for both. Clearly I am missing something. If someone could explain how I need to fix this, I would greatly appreciate it.
I want to concatenate an ID with the name of a product as shown in the following image
The problem is that the property that I load into the list is of type Object, here my data structure
public class FabricanteFormResponse
{
[JsonProperty(PropertyName = "results")]
public FabricanteForm Results { get; set; }
}
public class FabricanteForm
{
[JsonProperty(PropertyName = "columns")]
public List<int> Columns { get; set; }
[JsonProperty(PropertyName = "sqs")]
public List<List<Sqs>> Sqs { get; set; }
}
public class Sqs
{
[JsonProperty(PropertyName = "field")]
public string Field { get; set;}
[JsonProperty(PropertyName = "column")]
public int Column { get; set; }
[JsonProperty(PropertyName = "value")]
public Object Value { get; set; }
}
The logic is thus, when the column takes the value 2 it is a product and when the column takes the value 1 it is the ID.
then when I open my ViewModel I create an ObservableCollection of Sqs and a method LoadSubstances () that loads the list of this object of type Object when the column is 2 with LINQ
#region Constructor
public ResultadosHDSViewModel()
{
Sqss = new ObservableCollection<Sqs>();
LoadSustancias();
}
#endregion
#region Metodos
public async void LoadSustancias()
{
var mainViewModel = MainViewModel.GetInstance();
var sustancias = mainViewModel.FabricanteForm.Results.Sqs.Select(c => c.Where(v => v.Column == 2)
.Select(u => u).ToList()).ToList();
Sqss.Clear();
foreach (var item in sustancias)
{
foreach (var itemSqs in item)
{
if (itemSqs.Column == 2)
{
Sqss.Add(itemSqs);
}
}
}
}
#endregion
In my Vista I occupy the following bindings
<ListView ItemsSource="{Binding Sqss}"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal"
VerticalOptions="CenterAndExpand"
Padding="16,0,0,0">
<Label Text="{Binding Value}"
HorizontalOptions="FillAndExpand"
FontSize="Small"
TextColor="{StaticResource das.color.texto}"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
As occupying the data structure previously presented can I concatenate the ID together with the Product Name? Can I do it from my LoadSubstance Method? should I create a new property?
any help for me?
From the Sqs list of lists get the relevant item
List<Sqs> item = Sqs[i];
string formattedString = $"({item[0].Value}) {item[1].Value}";
// e.g. "(2) 10-31 LIMPIADOR DE CONTACTOS"
assuming that id and product are always the two first items.
But it would be much easier if you created a Product class and converted the raw Json properties list into a products list
public class Product
{
public Product()
{
}
public Product(List<Sqs> properties)
{
Id = (int)properties[0].Value;
Name = (string)properties[1].Value;
Manufacturer = (string)properties[2].Value;
Keywords = (string)properties[3].Value;
}
public int Id { get; set; }
public string Name { get; set; }
public string Manufacturer { get; set; }
public string Keywords { get; set; }
public string ProductText => $"({Id}) {Name}";
public override string ToString() => ProductText;
}
This class has a property ProductText and overrides ToString to let it produce your formatted string as desired.
Replace Sqss by Products
public ObservableCollection<Product> Products { get; set; }
Then you can simply create a products list in LoadSustancias() with
Products = new ObservableCollection<Product>(mainViewModel.FabricanteForm.Results.Sqs
.Select(props => new Product(props))
);
Now you can bind your ListView to a Products list and bind the label to <Label Text="{Binding ProductText}" ....
I have two tables named Process and ProcessTriggers. ProcessTriggers referring Process table.And need to create a screen to diplay Process as well as the ProcessTrigger related to the Process. I have created data objects using entity framework and my classes look like.
public partial class Process
{
public Process()
{
this.ProcessTriggers = new ObservableCollection<ProcessTrigger>();
}
public int ID { get; set; }
public int WorkflowID { get; set; }
public string Name { get; set; }
public bool IsBatch { get; set; }
public Nullable<System.DateTime> ModifiedOn { get; set; }
public virtual ObservableCollection<ProcessTrigger> ProcessTriggers { get; set; }
}
And my view model look like..
public class ProcessViewModel : ViewModel<Process>
{
private RelayCommand saveCommand;
private RelayCommand cancelCommand;
public ProcessViewModel()
{
using(var context = new PACEContext())
{
this.Entity = context.Processes.FirstOrDefault(i => i.ID == 1);
IsInEditMode = true;
}
}
}
I am binding these viewModel to my View, Entity properties are bound correctly, but the ProcessTriggerCollection is not binding to datagrid..
<DataGrid ItemsSource="{Binding Entity.ProcessTriggers}" AutoGenerateColumns="True">
</DataGrid>
I juts started learning WPF, MVVM and Entity framework.Can any one help.?
I understand the Process have a ObservableCollection of other class called ProcessTriggers.
Why you don't create a ObservableCollection and binding this?
private ObservableCollection<ProcessTrigger> _listProcessTriggers;
public ObservableCollection<ProcessTrigger> ListProcessTriggers
{
get { return _listProcessTriggers; }
set { _listProcessTriggers= value; RaisePropertyChanged("ListProcessTriggers"); }
}
public ProcessViewModel()
{
using(var context = new PACEContext())
{
this.Entity = context.Processes.FirstOrDefault(i => i.ID == 1);
ListProcessTriggers = Entity.ProcessTriggers;
IsInEditMode = true;
}
}
And In Xmal Binding
<DataGrid ItemsSource="{Binding ListProcessTriggers}" AutoGenerateColumns="True />
I am trying to create a binding source for a gridview that contains the datasource for a child gridview. I have attempted it in the following way:
I have 3 tables:
Patients: id(PK), fname, fname
Study: id(FK),study_id(PK),treatment_site,treatment_type,physician,dosimetrist
Study_Status:study_id(PK,FK),hasContours,hasPlan,isReady
I have the following model:
public class myPatient
{
public string fname { get; set; }
public string lname { get; set; }
public bool hascontours { get; set; }
public bool hasplan { get; set; }
public bool isready { get; set; }
public IEnumerable<editPatient> epr{ get; set; }
}
public class editPatient
{
public string fname { get; set; }
public string lname { get; set; }
public string txsite { get; set; }
public string txtype { get; set; }
public string physician { get; set; }
public string dosimetrist { get; set; }
}
public class myPatientList : List<myPatient>
{
public myPatientsList()
{
AddRange(getMyPatients().ToList());
}
public IEnumerable<myPatient> getMyPatients()
{
Connection plan_trackerEM = new Connection();
return from np in plan_trackerEM.patients
join ns in plan_trackerEM.studies on np.ID equals ns.Id
join nss in plan_trackerEM.study_status on ns.study_id equals nss.study_id
where ns.dosimetrist == App.userClass.user_id || ns.physician == App.userClass.user_id)
select new myPatient()
{
fname = np.fname,
lname = np.lname,
hascontours = nss.hasContours,
hasplan = nss.hasPlan,
isready = nss.isReady,
epr = getEditPatients(ns.study_id).ToList()
};
}
public IEnumerable<editPatient> getEditPatients(long study_id)
{
Connection plan_trackerEM = new Connection();
return from np in plan_trackerEM.patients
join ns in plan_trackerEM.studies on np.ID equals ns.Id
where ns.study_id == study_id
select new editPatient()
{
fname = np.fname,
lname = np.lname,
txsite = ns.treatment_site,
txtype = ns.treatment_type,
physician = ns.physician,
dosimetrist = ns.dosimetrist
};
}
}
Then I bind the data using XML
<local:myPatientsList x:Key="mPL"/>
<CollectionViewSource x:Key="MP" Source="{StaticResource mPL}"/>
<CollectionViewSource x:Key="EP" Source="{Binding epr, Source={StaticResource MP}}"/>
This errors out with: {"LINQ to Entities does not recognize the method 'System.Collections.Generic.List1[Plan_Tracker.editPatient] ToList[editPatient](System.Collections.Generic.IEnumerable1[Plan_Tracker.editPatient])' method, and this method cannot be translated into a store expression."}
Any pointers on how to get this to work would be greatly appreciated. The data that will be stored in the field "epr" will need to be editable by the user.
EDIT 2013-05-21
Ok, I might be getting closer with a very odd work around.
I removed
epr = getEditPatients(ns.study_id).ToList()
from the query results and then added after the query results:
List<mypatientResults> new_tmp_mp = new List<mypatientResults>();
foreach (mypatientResults tmp_mp in _mp)
{
tmp_mp.epr = getEditPatients(tmp_mp.sid).ToList();
new_tmp_mp.Add(tmp_mp);
}
return new_tmp_mp;
This is now runnign without error, but I have not been successful (YET) in using epr as a datasource. I have added it as a column to a datagrid for debugging and it does report it as a System.Collections.Generic.List`1[Plan_Tracker.editpatientResults], but that could be from declaring the variable and not because of the data.
I am still overmy head here and could use help figuring this out.
I am unsure the reasoning, possible that Linq does not like the tree-like structure?!? regardless the edited text above was the solution. I was able to successfully create custom hierarchy and show it in a parent/child gridview.