I have the following code in Wpf form:
public class Product
{
public string Name { get; set; }
public string Type { get; set; }
}
public class ProductWithValue
{
public Product Object_Product { get; set; }
public string Value { get; set; }
}
public class Data
{
public ObservableCollection<Product> ListProduct { get; set; }
public ObservableCollection<ProductWithValue> ListProdValue { get; set; }
}
Data data = LoadData();
lstProducts.DataContext = data;
The XAML:
<ListView Name="lstProducts" ItemsSource="{Binding Path=ListProdValue}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="23">
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.ListProduct}"
SelectedItem="{Binding Path=Object_Product, Mode=TwoWay}"
DisplayMemberPath="Name"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
LoadData example:
private Data LoadData()
{
Data data = new Data();
Product prod1 = new Product(){Name="Name1", Type = "Type1"};
Product prod2 = new Product(){Name="Name2", Type = "Type2"};
data.ListProduct = new ObservableCollection<Product>()
{
prod1,
prod2
};
data.ListProdValue = new ObservableCollection<ProductWithValue>()
{
new ProductWithValue(){ Object_Product = prod1, Value="Value" }
};
return data;
}
Evrything is fine, except the DisplayMemberPath.
The combobox itemssource is correct, the selected item is correct, but does not show the Name of the Product.
Any idea whats going wrong?
The wrong LoadData function in my code:
private Data LoadData()
{
Data data = new Data();
Product prod1 = new Product() { Name = "Name1", Type = "Type1" };
Product prod2 = new Product() { Name = "Name2", Type = "Type2" };
Product prod3 = new Product() { Name = "Name3", Type = "Type3" };
data.ListProduct = new ObservableCollection<Product>()
{
prod1,
prod2,
prod3
};
data.ListProdValue = new ObservableCollection<ProductWithValue>()
{
new ProductWithValue(){ Object_Product = new Product() { Name = "Name1", Type = "Type1" }, Value="Value1" },
new ProductWithValue(){ Object_Product = new Product() { Name = "Name2", Type = "Type2" }, Value="Value2" }
};
return data;
}
Related
Im trying to bind one combobox from my class that i linked in the context
i have this in the control
<dxe:ComboBoxEdit Width="100" Margin="5" Name="cboProduct" DisplayMember="Name"
SelectedItem="{Binding Path=DataContext.SelectedProduct, Mode=OneWay, RelativeSource={RelativeSource AncestorType=Window}}"
>
</dxe:ComboBoxEdit>
I filled the Combobox befor from code behind like this
var lsproducts = new List<Product>();
var Products =_licenseService.GetProductList();
Products.ForEach((x) => {
lsproducts.Add(new Product(x.Name, x.ProductId));
});
And im setting the SelectedProduct like this
[DataMember]
public License SelectedLicense {
get { return _SelectedLicense;}
set {
_SelectedLicense = value;
this.NotifyPropertyChanged("SelectedLicense");
}
}
public Product SelectedProduct
{
get
{
return new Product(_SelectedLicense.Product.Name,_SelectedLicense.Product.ProductId);
}
}
this.cboProduct.ItemsSource = lsproducts.ToArray();
in both cases im using the object Product
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using pd.Common.Domain;
namespace LicenceManagerWPF.Views
{
public class Product
{
public string Name { get; set; }
public ProductEnum ProductID { get; set; }
public Product(string ProductName,ProductEnum ID)
{
Name = ProductName;
ProductID = ID;
}
}
i dont know why its not selecting the product when i open the window.
i have another one
[![Shows like this][2]][2]
I dont know why its display the x mark, but when i chouse another licence it updated the combo selection
<dxe:ComboBoxEdit x:Name="cboActivationMode" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" Width="100" Style="{StaticResource TabMargin}"
SelectedItem="{Binding Path=DataContext.SelectedLicense.ActivationMode, RelativeSource={RelativeSource AncestorType=Window}}"
/>
The second one its only a couple of enums values that fill like this.
cboActivationMode.Items.Add(
new DevExpress.Xpf.Editors.ComboBoxEditItem()
{ Content = Enum.GetName(typeof(ActivationMode), ActivationMode.Online), Tag = ActivationMode.Online });
How can i bind the values to a combobox?
Regards
cboActivationMode.Items.Add(
new DevExpress.Xpf.Editors.ComboBoxEditItem()
{Content = Enum.GetName(typeof(ActivationMode), ActivationMode.Offline),Tag = ActivationMode.Offline});
I tryed to do this
public partial class LicenseDetail : UserControl
{
private readonly LicenseService _licenseService;
public LicenseDetail()
{
InitializeComponent();
_licenseService = new LicenseService();
FillCombos();
}
private void FillCombos()
{
FillProducts();
FillActivationMode();
//var str = Enum.GetName(typeof(ProductEnum), ProductEnum.CDSAddIn);
//this.cboProduct.ItemsSource = new string[] { str };
}
private void FillProducts()
{
var Products = _licenseService.GetProductList();
cboProduct.ItemsSource = Products;
}
The product list is a list of Iproduct (interface), i dont get i why they made it like this but each product is diferent they implement the same baseclass and the interface
[DataContract]
public class ProductList : List<IProduct>
{
public bool Contains(ProductEnum productId)
{
return this.Any(x => x.ProductId == productId);
}
public IProduct GetProduct(ProductEnum productId)
{
return this.FirstOrDefault(x => x.ProductId == productId);
}
public void Remove(ProductEnum productId)
{
Remove(GetProduct(productId));
}
}
I changed the combo to bind like this
SelectedItem="{Binding Path=DataContext.MyProduct, RelativeSource={RelativeSource AncestorType=Window}}"
I create the property in the class like this
public IProduct MyProduct
{
get { return _MyProduct; }
set
{
_MyProduct = value;
this.NotifyPropertyChanged("MyProduct");
}
}
And assaing like this
_CustomerLicense.MyProduct = SelectedLicense.Product;
this is how the list of products is filled
public IProduct GetProduct(ProductEnum productId)
{
IProduct product = null;
var connection = GetConnection();
try
{
var sql = string.Format(Resources.GetProduct, (int)productId);
var cmd = new SqlCommand(sql, connection) { CommandType = CommandType.Text, Transaction = _transaction };
using (var rdr = new NullableDataReader(cmd.ExecuteReader()))
while (rdr.Read())
{
var productName = rdr.GetString(0);
var featureId = rdr.GetInt32(1);
var featureDesc = rdr.GetString(2);
if (product == null)
{
switch (productId)
{
case ProductEnum.PDCalc:
product = new PDCalcProduct(productId, productName);
break;
case ProductEnum.PDMaint:
product = new PDMaintProduct(productId, productName);
break;
case ProductEnum.PBDynamics:
product = new PBDynamicsProduct(productId, productName);
break;
case ProductEnum.CDSAddIn:
product = new CDSAddInProduct(productId, productName);
break;
}
}
if (product != null)
product.Features.Add(new Feature((FeatureEnum)featureId, featureDesc));
}
}
finally
{
CloseConnection(connection);
}
return product;
}
without any luck.
Regards
The SelectedProduct property should have a public setter for you to be able to set it to the currently selected value in the ComboBox:
private Product _selectedProduct;
public Product SelectedProduct
{
get { return _selectedProduct; }
set
{
_selectedProduct = value;
this.NotifyPropertyChanged("SelectedProduct");
}
}
And for the intial value to be selected, you either need to set it to a Product object that is actually in the ItemsSource (lsproducts):
viewModel.SelectedProduct = lsproducts.FirstOrDefault(x => x.Name == _SelectedLicense.Product.Name && x.ProductID == _SelectedLicense.Product.ProductId);
Or you will have to override the Equals method of your Product class:
public class Product
{
public string Name { get; set; }
public ProductEnum ProductID { get; set; }
public Product(string ProductName, ProductEnum ID)
{
Name = ProductName;
ProductID = ID;
}
public override bool Equals(object obj)
{
Product other = obj as Product;
return other != null && Name == other.Name && ProductID == other.ProductID;
}
}
I fixed like this:
I created the method :
private void GetProducts()
{
var Products = new LicenseService().GetProductList();
Products.ForEach((x) =>
{
lsproducts.Add(new Product(x.Name, x.ProductId));
});
//this.cboProduct.ItemsSource = lsproducts.ToArray();
}
Then i attached to the load of the main windows, where all the controls are
public frmCustomerLicense(CustomerLicenses cl)
{
InitializeComponent();
GetProducts();
_CustomerLicense = cl;
grdLicenses.grdLicences.SelectedItemChanged += GridRowSelected;
}
Then when one of the licenses is selected i set all the bindings
var Record = (DataRowView)grdLicenses.grdLicences.SelectedItem;
var SelectedLicense = (License)Record["License"];
var list = new LicenseService().GetActivityLog(SelectedLicense.SerialNumber)
.OrderByDescending(x => x.ActivityDate)
.ToList();
_CustomerLicense.ActivityLog = list;
_CustomerLicense.Features = new LicenseService().GetFeatures(SelectedLicense.Product.ProductId);
_CustomerLicense.Products = lsproducts;
_CustomerLicense.HasExpDate = SelectedLicense.HasExpirationDate;
//_CustomerLicense.SetLog(list);
_CustomerLicense.SelectedLicense = SelectedLicense;
//_CustomerLicense.SelectedMaintenance = SelectedLicense.Product.ProductId == ProductEnum.PDMaint ? true : false;
_CustomerLicense.SelectedProduct = lsproducts.FirstOrDefault((x) => x.ProductID == SelectedLicense.Product.ProductId);
And in my ViewClass i added this
[DataMember]
public Product SelectedProduct
{
get { return _SelectedProduct; }
set
{
_SelectedProduct = value;
this.NotifyPropertyChanged("SelectedProduct");
}
}
[DataMember]
public List<Product> Products
{
get { return _Products; }
set { _Products = value;
this.NotifyPropertyChanged("Products");
}
}
So, i set the combobox
<dxe:ComboBoxEdit Width="180" Margin="5" Name="cboProduct" DisplayMember="Name"
ItemsSource="{Binding Path=DataContext.Products, RelativeSource={RelativeSource AncestorType=Window}}"
SelectedItem="{Binding Path=DataContext.SelectedProduct, RelativeSource={RelativeSource AncestorType=Window}}"
>
</dxe:ComboBoxEdit>
Doing this works, thanks for your help mm8
I'm using MVVM pattern, developing my WPF application. I also use Entity Framework as ORM. Here're my models (EF):
public class User : BaseEntity
{
public string Name { get; set; }
public int OfficeId { get; set; }
public Office Office { get; set; }
}
public class Office : BaseEntity
{
public string Name { get; set; }
public int DepartmentId { get; set; }
public Department Department { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public class Department : BaseEntity
{
public string Name { get; set; }
public virtual ICollection<Office> Offices { get; set; }
}
Let's assume, that I've got an instance of User class from my context:
var userInstance = context.Get<User>().Single(user => user.ID == 1);
Now I'd like to pass this instance to my View to make some changes for concrete user (called, for example, UserEditView), so I have to create a UserModel class to deal with User data according to MVVM. So, here's what I think I have to write in my code:
public class UserModel : ObservableObject
{
private User user;
public string Office Office
{
get
{
return this.user.Office.Name;
}
set
{
//what shoud I write Here??
if(value != user.Office)
{
user.Office=value;
OnPropertyChanged("Office");
}
}
}
}
I'm really frustrated! How should I deal with that? There're thousands of examples, but they are so simple. I'm wondering what should I do to have a ComboBox in my EditView with a list of all Offices, existing in my DB. And list of Offices should depend on another one Combobox, which contains a list of Departments.
But where should I get this lists from?
Should I pass a collection from my UserModel? Or what?
Can anybody give me a simple example about how to do this correctly?
PS: Of course, I know couple ways to implement such behaviour, but in that case my code seems to be ugly and not maintainable. Please, help. Thanks a lot!
this is depends on your DB architecture. Here is some common suggestion (but there can be a lot of others).
Don't panic - you have a correct question.
Create the view model set it to be a main view model of your window.
In your view model create two collections Users (containing UserModels) and Departments (containing DepartmentMode), since you want to change offices each time you re-select department, you don't need the Offices collection in main view model.
Pull each collection data from your data base.
Implement each model with INPC.
Take in account the WPF MVVM best practices.
Apply a correct bindings.
And be happy - you are a programmer.
Updates - 1
XAML code
<Grid x:Name="LayoutRoot">
<Grid.DataContext>
<someBindingExampleSoHelpAttempt:MainViewModel/>
</Grid.DataContext>
<ListView ItemsSource="{Binding Users}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate DataType="someBindingExampleSoHelpAttempt:UserModel">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="200"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="{Binding Name, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="{Binding LastName, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>
<ComboBox Grid.Column="2"
IsTextSearchEnabled="True"
IsTextSearchCaseSensitive="False"
StaysOpenOnEdit="True"
TextSearch.TextPath="DepartmentName"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type ListView}}, Path=DataContext.Departments}"
SelectedValue="{Binding Department}"
DisplayMemberPath="DepartmentName"
IsEditable="True"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
<ComboBox Grid.Column="3"
IsTextSearchEnabled="True"
IsTextSearchCaseSensitive="False"
StaysOpenOnEdit="True"
IsEditable="True"
TextSearch.TextPath="OfficeName"
ItemsSource="{Binding OfficesCollection}"
SelectedValue="{Binding Office}"
DisplayMemberPath="OfficeName"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView></Grid>
VM and models
public class MainViewModel:BaseObservableObject
{
private DepartmentModel _selectedDepartment;
private OfficeModel _selectedOffice;
public MainViewModel()
{
Dal = new DataLayer();
Users = new ObservableCollection<UserModel>();
Departments = new ObservableCollection<DepartmentModel>(Dal.GetAllDepartments());
InitUsersCollection();
}
private void InitUsersCollection()
{
if(Departments == null) return;
Departments.ToList().ForEach(model =>
{
model.Offices.ToList().ForEach(officeModel =>
{
if (officeModel.Users == null) return;
officeModel.Users.ToList().ForEach(userModel => Users.Add(userModel));
});
});
}
public ObservableCollection<UserModel> Users { get; set; }
public ObservableCollection<DepartmentModel> Departments { get; set; }
private DataLayer Dal { get; set; }
}
public class DataLayer
{
public List<DepartmentModel> GetAllDepartments()
{
//pull and map your using your DB service
//For example:
return new List<DepartmentModel>
{
new DepartmentModel
{
DepartmentId = 1,
DepartmentName = "A",
Offices = new ObservableCollection<OfficeModel>
{
new OfficeModel
{
DepartmentId = 1,
OfficeName = "AA",
Users = new ObservableCollection<UserModel>(new List<UserModel>
{
new UserModel {Name = "Avicenna", LastName = "Abu Ali Abdulloh Ibn-Sino"},
new UserModel {Name = "Omar", LastName = "Khayyam"},
new UserModel {Name = "RAMBAM", LastName = "Moshe ben Maimon"}
})
},
new OfficeModel
{
DepartmentId = 1,
OfficeName = "AB",
Users = new ObservableCollection<UserModel>(new List<UserModel>
{
new UserModel {Name = "Leo", LastName = "Tolstoi"},
new UserModel {Name = "Anton", LastName = "Chekhov"},
})},
}
},
new DepartmentModel
{
DepartmentId = 2,
DepartmentName = "B",
Offices = new ObservableCollection<OfficeModel>
{
new OfficeModel
{
DepartmentId = 2, OfficeName = "BA",
Users = new ObservableCollection<UserModel>(new List<UserModel>
{
new UserModel {Name = "B", LastName = "O"},
new UserModel {Name = "B", LastName = "N"},
}),
},
new OfficeModel
{
DepartmentId = 2, OfficeName = "BB",
Users = new ObservableCollection<UserModel>(new List<UserModel>
{
new UserModel {Name = "John", LastName = "Walker"},
new UserModel {Name = "Gregory", LastName = "Rasputin"},
}),
},
}
},
new DepartmentModel
{
DepartmentId = 3,
DepartmentName = "C",
Offices = new ObservableCollection<OfficeModel>
{
new OfficeModel {DepartmentId = 3, OfficeName = "CA"},
new OfficeModel {DepartmentId = 3, OfficeName = "CB"},
new OfficeModel {DepartmentId = 3, OfficeName = "CC"}
}
}
};
}
}
public class OfficeModel:BaseObservableObject
{
private int _departmentModel;
private string _officeName;
private DepartmentModel _department;
private ObservableCollection<UserModel> _users;
public int DepartmentId
{
get { return _departmentModel; }
set
{
_departmentModel = value;
OnPropertyChanged();
}
}
public DepartmentModel Department
{
get { return _department; }
set
{
_department = value;
OnPropertyChanged();
}
}
public string OfficeName
{
get { return _officeName; }
set
{
_officeName = value;
OnPropertyChanged();
}
}
public ObservableCollection<UserModel> Users
{
get { return _users; }
set
{
_users = value;
OnPropertyChanged(()=>Users);
}
}
}
public class DepartmentModel:BaseObservableObject
{
private string _departmentName;
public string DepartmentName
{
get { return _departmentName; }
set
{
_departmentName = value;
OnPropertyChanged();
}
}
public int DepartmentId { get; set; }
public ObservableCollection<OfficeModel> Offices { get; set; }
}
public class UserModel:BaseObservableObject
{
private string _name;
private string _lastName;
private DepartmentModel _department;
private OfficeModel _office;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
}
}
public string LastName
{
get { return _lastName; }
set
{
_lastName = value;
OnPropertyChanged();
}
}
public DepartmentModel Department
{
get { return _department; }
set
{
_department = value;
OnPropertyChanged();
OnPropertyChanged(()=>OfficesCollection);
}
}
public ObservableCollection<OfficeModel> OfficesCollection
{
get { return Department.Offices; }
}
public OfficeModel Office
{
get { return _office; }
set
{
_office = value;
OnPropertyChanged();
}
}
}
/// <summary>
/// implements the INotifyPropertyChanged (.net 4.5)
/// </summary>
public class BaseObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> raiser)
{
var propName = ((MemberExpression)raiser.Body).Member.Name;
OnPropertyChanged(propName);
}
protected bool Set<T>(ref T field, T value, [CallerMemberName] string name = null)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
OnPropertyChanged(name);
return true;
}
return false;
}
}
But please take in account that this is only one of hundreds ways to do that.
The SO here if you will need the code example.
Regards.
I have a class as below
public class Account
{
public string TransferFromIndicator { get; set; }
public string AccNickname { get; set; }
public string AccountStatus { get; set; }
public string AccIndex { get; set; }
public SolidColorBrush RowColor { get; set; }
}
All the data other than RowColor property is being set from backend data. While retriving the data from backend I want to select every alternate color as Black i.e first items color as White next items color is white this goes on. I have been trying to do this with below snippet. Can you please help me how could I set up different rowcolor for alternate elements.
List<Account> newList = from x in AccountList select new Account
{
TransferFromIndicator=TransferFromIndicator
AccNickname = AccNickname,
RowColor =
}
Try this:
XAML:
<ListBox x:Name="lst">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding AccNickname}" Foreground="{Binding RowColor}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
CS:
public class Account
{
public string TransferFromIndicator { get; set; }
public string AccNickname { get; set; }
public string AccountStatus { get; set; }
public string AccIndex { get; set; }
public string RowColor { get; set; }
public Account() { }
public Account(string TransferFromIndicator,string AccNickname,string AccountStatus,string AccIndex,string RowColor)
{
this.TransferFromIndicator = TransferFromIndicator;
this.AccNickname = AccNickname;
this.AccountStatus = AccountStatus;
this.AccIndex = AccIndex;
this.RowColor = RowColor;
}
}
void loadData()
{
List<Account> objAccount = new List<Account>();
objAccount.Add(new Account("data", "data", "data", "data", "White"));
objAccount.Add(new Account("data", "data", "data", "data", "Black"));
objAccount.Add(new Account("data", "data", "data", "data", "White"));
objAccount.Add(new Account("data", "data", "data", "data", "Black"));
objAccount.Add(new Account("data", "data", "data", "data", "White"));
objAccount.Add(new Account("data", "data", "data", "data", "Black"));
lst.ItemsSource = objAccount;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
loadData();
}
I usually use a converter for this. there is also an alternate row color implementation floating around the internet for a listbox control.
Doing it your way:
public class Account
{
public string TransferFromIndicator { get; set; }
public string AccNickname { get; set; }
public string AccountStatus { get; set; }
public string AccIndex { get; set; }
public SolidColorBrush RowColor { get; set; }
}
public class MyViewModel
{
public void BindData()
{
var accounts = new List<Account>
{
new Account { AccIndex = "One", AccNickname = "First Account", AccountStatus = "Closed", TransferFromIndicator = "xyz" },
new Account { AccIndex = "Two", AccNickname = "Second Account", AccountStatus = "Open", TransferFromIndicator = "xyz" },
new Account { AccIndex = "Third", AccNickname = "Third Account", AccountStatus = "Pending", TransferFromIndicator = "xyz" },
new Account { AccIndex = "Fourth", AccNickname = "Fourth Account", AccountStatus = "Closed", TransferFromIndicator = "xyz" },
new Account { AccIndex = "Fifth", AccNickname = "Fifth Account", AccountStatus = "Open", TransferFromIndicator = "xyz" },
new Account { AccIndex = "Sixth", AccNickname = "Sixth Account", AccountStatus = "Pending", TransferFromIndicator = "xyz" }
};
var index = 0;
accounts.ForEach(a => { a.RowColor = ((index % 2 == 0) ? new SolidColorBrush(Colors.Red) : new SolidColorBrush(Colors.Green)); index++; });
}
}
First of all correct you tag. Do you need solution for WPF or Windows Phone ? Try below given code.
XAML
<Page.Resources>
<local:AlternateColor x:Name="AlternateColor" />
</Page.Resources>
<Grid>
<ListBox x:Name="lbx">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Background="{Binding Converter={StaticResource AlternateColor}}">
<TextBlock Text="{Binding TransferFromIndicator}" Foreground="GreenYellow" />
<TextBlock Text="{Binding AccNickname}" Foreground="GreenYellow"/>
<TextBlock Text="{Binding AccountStatus}" Foreground="GreenYellow"/>
<TextBlock Text="{Binding AccIndex}" Foreground="GreenYellow"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
To get data
var list = new List<Account>();
for (int i = 0; i < 10; i++)
{
list.Add(new Account
{
AccIndex = Path.GetRandomFileName(),
AccNickname = Path.GetRandomFileName(),
AccountStatus = Path.GetRandomFileName(),
TransferFromIndicator = Path.GetRandomFileName()
});
}
/*if you don't want to use converter
List<Account> newList = from x in AccountList select s;
bool ThrowBlack = false;
foreach (var item in s)
{
if (ThrowBlack)
{
ThrowBlack = false;
item.RowColor = new SolidColorBrush(Windows.UI.Colors.Black);
}
else
{
ThrowBlack = true;
item.RowColor = new SolidColorBrush(Windows.UI.Colors.White);
}
}
*/
lbx.ItemsSource = list;
Converter
public class AlternateColor : IValueConverter
{
bool ThrowBlack = false;
public object Convert(object value, Type targetType, object parameter, string language)
{
var obj = (Account)value;
if (ThrowBlack)
{
ThrowBlack = false;
obj.RowColor = new SolidColorBrush(Windows.UI.Colors.Black);
return obj.RowColor;
}
else
{
ThrowBlack = true;
obj.RowColor = new SolidColorBrush(Windows.UI.Colors.White);
return obj.RowColor;
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
I am having a few struggles on how to wire up my interconnected comboboxes when using MVVM. I have a DTO that represents an Order which contains a CustomerId and an OrderTypeId. Thesere are then wrapped inside an OrderViewModel. I also have an EditOrderViewModel which loads from a db a list of Customers.
What I would like to do is Load an Order from the DB (similar to the Load function) choose the right item in the ComboBox (the items source of which is a List, display the name of the selected customer in a text block to the right of the combobox and finally load the list of OrderTypes that belong to that Customer in the next combobox and again select the correct OrderType and display the OrderTypeName in a TextBlock to the right.
I have managed to get some of the behaviour to work when I use SelectedItem from the combobox but this is only when I select the item manually as I am not sure how in my viewmodel I can convert Order.CustomerId (type int) into the correct SelectedItem (type CustomerDTO). Below is some code which shows generally what I am trying to achieve whilst using in-memory datasources. Thanks Alex
<ComboBox Height="25" Width="150" ItemsSource="{Binding Path=Customers}" SelectedValue="{Binding Path=Order.CustomerId}" SelectedValuePath="Id">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Code}"></TextBlock>
<TextBlock Text="{Binding Path=Name}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Text="{Binding Path=Name,Mode=OneWay,NotifyOnSourceUpdated=True}"></TextBlock>
public class EditOrderViewModel : VMBase
{
public OrderViewModel Order{get;set;}
public void Load()
{
Order = new OrderViewModel(new OrderDto{CustomerId=1,OrderTypeId=2});
Order.PropertyChanged += MainWindowViewModel_PropertyChanged;
}
public EditOrderViewModel()
{
Order = new OrderViewModel(new OrderDto());
Order.PropertyChanged += OrderViewModel_PropertyChanged;
Customers = new List<CustomerDto> {
new CustomerDto{ Id = 1, Code = "ACME", Name = "ACME CORP" },
new CustomerDto{ Id = 2, Code = "MSFT", Name="MICROSOFT CORP" },
new CustomerDto{ Id = 3, Code = "APP", Name = "APPLE" }};
OrderTypes = new List<OrderTypeDto>{
new OrderTypeDto{OrderTypeId=1, CustomerId =1, Name = "Cake Order"},
new OrderTypeDto{OrderTypeId=2, CustomerId =1, Name = "Sandwich Order"},
new OrderTypeDto{OrderTypeId=3, CustomerId =2, Name = "Chocolate Order"},
new OrderTypeDto{OrderTypeId=4, CustomerId =2, Name = "Bread Order"},
new OrderTypeDto{OrderTypeId=5, CustomerId =3, Name = "Drinks Order"}};
}
void OrderViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "OrderTypeId":
break;
case "SelectedCustomer":
break;
default:
break;
}
}
public List<OrderTypeDto> OrderTypes { get; set; }
public List<CustomerDto> Customers { get; set; }
}
public class OrderDto
{
public int CustomerId { get; set; }
public int OrderTypeId { get; set; }
}
public class CustomerDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
}
public class OrderViewModel : VMBase
{
private OrderDto _orderDto;
private string _customerName;
public OrderViewModel(OrderDto orderDto)
{
_orderDto = orderDto;
}
public int CustomerId {
get { return _orderDto.CustomerId; }
set
{
_orderDto.CustomerId = value;
RaisePropertyChanged("CustomerId");
}
}
public string CustomerName {
get { return _customerName; }
set {_customerName = value;
RaisePropertyChanged("CustomerName");
}
}
public int OrderTypeId
{
get { return _orderDto.OrderTypeId; }
set
{
_orderDto.OrderTypeId = value;
RaisePropertyChanged("OrderTypeId");
}
}
}
Don't set ComboBox.SelectedValue in your XAML binding. You should be binding ComboBox.SelectedItem to your model so you can have the CustomDTO easily available. You should add a property to your OrderViewModel called Customer (of type CustomerDTO) instead of trying to recreate the CustomerDTO using several properties (CustomerID, CustomerName, etc.).
i have big problem with binding Stacked Column Series to my chart.
I have
public ObservableCollection Series property in my ViewModel and try by many ways but it still not working.
This is code from ViewModel to prepare Series:
private void drawChart()
{
this.Series.Clear();
var dataValues = new List<List<SimpleDataValue>>();
int wartoscNiezalezna = 1;
for (int i = 0; i < 2; i++)
{
dataValues.Add(new List<SimpleDataValue>());
}
foreach (var item in myCollection)
{
var param = someparam;
dataValues[0].Add(new SimpleDataValue { IndependentValue = "Czujnik " + wartoscNiezalezna, DependentValue = 100 });
//czerwone
dataValues[1].Add(new SimpleDataValue { IndependentValue = "" + wartoscNiezalezna, DependentValue = 200 });
wartoscNiezalezna++;
}
var stackedSeries = Activator.CreateInstance(typeof(StackedColumnSeries)) as DefinitionSeries;
int itemnr=0;
foreach (var item in dataValues)
{
var definicja = new SeriesDefinition();
if(itemnr==0)
definicja.Title = "Stan 1";
else
definicja.Title = "Stan 2";
definicja.DependentValuePath = "DependentValue";
definicja.IndependentValuePath = "IndependentValue";
definicja.ToolTip = "asdas";
definicja.ItemsSource = item;
stackedSeries.SeriesDefinitions.Add(definicja);
itemnr++;
}
Series.Add(stackedSeries);
}
I cant bind it to:
<charting:Chart x:Name="MyChart" Padding="10,10,10,10">
<charting:Chart.Series>
<charting:StackedColumnSeries>
<charting:SeriesDefinition ItemsSource="{Binding Series}" DependentValuePath="DependentValue" IndependentValuePath="IndependentValue">
</charting:SeriesDefinition>
</charting:StackedColumnSeries>
</charting:Chart.Series>
</charting:Chart>
I was trying with SeriesDefinitions Collection and others.
I will be very grateful to some help.
I hope I've answered your question there
Anyway I post the second part of my answer here:
MainWindow.xaml:
<charting:Chart x:Name="MyChart" Padding="10,10,10,10">
<charting:Chart.Series>
<charting:StackedColumnSeries>
<charting:SeriesDefinition Title="Stan 1" ItemsSource="{Binding FirstCollection}" DependentValuePath="DependentValue" IndependentValuePath="IndependentValue" />
<charting:SeriesDefinition Title="Stan 2" ItemsSource="{Binding SecondCollection}" DependentValuePath="DependentValue" IndependentValuePath="IndependentValue" />
</charting:StackedColumnSeries>
</charting:Chart.Series>
</charting:Chart>
MainWindow.xaml.cs
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
this.MyChart.DataContext = new ChartModel
{
FirstCollection = Enumerable.Range(1, 10).Select(i => new SimpleDataValue { IndependentValue = "Czujnik " + i, DependentValue = 100 }).ToList(),
SecondCollection = Enumerable.Range(1, 10).Select(i => new SimpleDataValue { IndependentValue = "" + i, DependentValue = 200 }).ToList()
};
}
}
public class SimpleDataValue
{
public string IndependentValue { get; set; }
public int DependentValue { get; set; }
}
public class ChartModel
{
public List<SimpleDataValue> FirstCollection { get; set; }
public List<SimpleDataValue> SecondCollection { get; set; }
}
I am not sure with the syntax but the logic should be like below:
ViewModel
public class GraphItem {
public string IndependentValue { get; set; }
public int DependentValue1 { get; set; }
public int DependentValue2 { get; set; }
}
public class ChartViewModel
{
private List<GraphItem> itemCollection;
public List<GraphItem> ItemCollection
{
get { return itemCollection;}
set {
itemCollection=value;
OnPropertyChanged("ItemCollection");
}
}
public ChartViewModel()
{
//Bind ItemCollection
}
}
Xaml:
<charting:Chart x:Name="MyChart" Padding="10,10,10,10" DataContext={Binding ItemCollection}">
<charting:Chart.Series>
<charting:StackedColumnSeries>
<charting:SeriesDefinition Title="Stan 1" ItemsSource="{Binding}" DependentValuePath="DependentValue1" IndependentValuePath="IndependentValue" />
<charting:SeriesDefinition Title="Stan 2" ItemsSource="{Binding}" DependentValuePath="DependentValue2" IndependentValuePath="IndependentValue" />
</charting:StackedColumnSeries>
</charting:Chart.Series>
</charting:Chart>
May this help.