I have a ListView of which ItemSource is set to my Custom Collection.
I have defined a GridView CellTemplate that contains a combo box as below :
<ListView
MaxWidth="850"
Grid.Row="1"
SelectedItem="{Binding Path = SelectedCondition}"
ItemsSource="{Binding Path = Conditions}"
FontWeight="Normal"
FontSize="11"
Name="listview">
<ListView.View>
<GridView>
<GridViewColumn
Width="175"
Header="Type">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox
Style="{x:Null}"
x:Name="TypeCmbox"
Height="Auto"
Width="150"
SelectedValuePath="Key"
DisplayMemberPath="Value"
SelectedItem="{Binding Path = MyType}"
ItemsSource="{Binding Path = MyTypes}"
HorizontalAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</ListView>
public MyType : INotifyPropertyChanged
{
string Key;
string Value;
public string Key { get { return _key; }
set { _key = value; this.OnPropertyChanged("Key"); } }
public string Value { get { return _value; }
set { _value = value; this.OnPropertyChanged("Value"); } }
public MyType ()
{
}
public MyType (string key, string value)
{
_key = key;
_value = value;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public void MoveUpExecuted()
{
int oldIndex = this.Conditions.IndexOf(_selectedCondition);
//Check if the selected item is not the first item
if (oldIndex != 0)
{
int newIndex = oldIndex - 1;
this.Conditions.Move(oldIndex, newIndex);
}
}
My Custom collection is the ObservableCollection.
I have a two buttons - Move Up and Move Down on top of the listview control . When user clicks on the Move Up or Move Down button I call Move method of Observable Collection.
But when I Move Up and Move Down the rows then the Selected Index of a combo box is -1.
I have ensured that selectedItem is not equal to null when performing Move Up and Move Down commands.
Please Help!!
I don't get this part:
I call MoveUp and MoveDown methods of
Observable Collection.
ObservableCollection does not have such methods, at least not to my knowledge? Neither has it a notion of a current item or similar.
My apologies if I have missed something that could possibly render this post as ignorant.
What you could do is instead of binding your ListView to an ObservableCollection, you could bind it to a ICollectionView (derived from your ObservableCollection). If you set IsSynchronizedWithCurrentItem=True on ListView, you won't need to bind SelectedItem, it will be automatically bound to CurrentItem on ICollectionView.
ICollectionView also implements MoveCurrentToNext and MoveCurrentCurrentToPrevious which can be bound from your buttons (via ICommand).
EDIT:
Now that new information is on the table, my above answer is not really relevant anymore. But I don't (yet) know the SO convention how to handle this, if I should delete the post entirely, edit out the above or just add the "new" reply. For now I'll edit this post.
I tried to recreate your project and your problem. Hopefully I have understood your problem right, and recreated it similarly at least.
As in the problem being the combobox not holding its value when it is being moved in the listview, it works for me.
Below are the relevant code (some of it hidden to avoid too much noise).
Does this help you?
public class MainWindowViewModel:INotifyPropertyChanged
{
private Condition _selectedCondition;
public ObservableCollection<Condition> Conditions { get; set; }
public Condition SelectedCondition
{
get
{
return _selectedCondition;
}
set
{
if (_selectedCondition != value)
{
_selectedCondition = value;
OnPropertyChanged("SelectedCondition");
}
}
}
...
public void MoveUpExecuted()
{
int oldIndex = this.Conditions.IndexOf(_selectedCondition);
//Check if the selected item is not the first item
if (oldIndex != 0)
{
int newIndex = oldIndex - 1;
this.Conditions.Move(oldIndex, newIndex);
}
}
And the condition class:
public class Condition : INotifyPropertyChanged
{
private MyType myType;
public ObservableCollection<MyType> MyTypes { get; set; }
public MyType MyType
{
get { return myType; }
set
{
if (myType != value)
{
myType = value;
OnPropertyChanged("MyType");
}
}
}
public Condition()
{
MyTypes = new ObservableCollection<MyType>() { new MyType() { Key = "1", Value = "One" }, new MyType() { Key = "2", Value = "Two" } };
MyType = MyTypes[1];
}
... etc
<ListView
SelectedItem="{Binding Path=SelectedCondition}"
ItemsSource="{Binding Path=Conditions}"
FontWeight="Normal"
FontSize="11"
Name="listview" Margin="0,32,0,0">
<ListView.View>
<GridView>
<GridViewColumn
Width="175"
Header="Type">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox
Width="150"
SelectedValuePath="Key"
DisplayMemberPath="Value"
SelectedItem="{Binding Path=MyType}"
ItemsSource="{Binding Path=MyTypes}"
HorizontalAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<Button Content="Move up"
Command="{Binding MoveUpCommand}"
/>
Swap these lines:
SelectedItem="{Binding Path = SelectedCondition}"
ItemsSource="{Binding Path = Conditions}"
ItemSource needs to be before the SelectedItem
Did you try ItemsSource="{Binding Conditions}"
Related
I want to set selected value of a combobox
I am receiving a DataTable from the database looking like this:
this Datatable is bound to this combobox.
<ComboBox
DisplayMemberPath="KommuneNavn"
SelectedValuePath="KommuneNr"
ItemsSource="{Binding KommuneNavne}"
SelectedValue="{Binding KommuneNr, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Margin="3"
IsEnabled="{Binding IsUdenlandskAdresse, Converter={StaticResource BooleanNotConverter}}" />
In my viewmodel I have a specific KommuneNr stored in a property. I would like to have my combobox set to show the KommuneNavn that matches with this KommuneNr.
Example:
I have the KommuneNr 101 stored in my viewmodel, the KommuneNavn that matches with this is København I would then like to have my combobox be set to København.
This was pretty difficult to explain, I hope I am making sense. Otherwise feel free to ask.
KommuneNavne must be an ObservableCollection, and in your ViewModel you should implement INotifyPropertyChanged (not described in this example)
<ComboBox
ItemsSource="{Binding KommuneNavne}"
SelectedValue="{Binding KommuneNr, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="KommuneNavn"
SelectedValuePath="KommuneNr"
/>
ViewModel
public class MyViewModel : INotifyPropertyChanged
{
public ObservableCollection<KommuneNavn> KommuneNavne
{
get { value = _kommuneNavne; } //=> _kommuneNavne;
set
{
_kommuneNavne = value;
OnPropertyChanged(nameof(KommuneNavne));
}
}
public long KommuneNr
{
get { value = _kommuneNr; } //=> _kommuneNr;
set
{
if (_kommuneNr == value) return;
_kommuneNr = value;
OnPropertyChanged(nameof(KommuneNr));
}
}
private void SetValue(int valueToSet)
{
KommuneNr = valueToSet;
}
}
I have a simple class as such:
public class Item
{
public int ID{get;set;}
public string Name{get;set;}
}
I have a List of this class in my Mainwindow.xaml.cs as such:
public List<Item> AllItems=GetAllItems();
I have four properties of Item class in my Mainwindow.xaml.cs as such:
public Item Item1{get;set;}
public Item Item2{get;set;}
public Item Item3{get;set;}
public Item Item4{get;set;}
This List:AllItems is databinded to four Comboboxes as under:
<ComboBox x:Name="cmbCode1" ItemsSource="{Binding AllItems}" DisplayMemberPath="ID" SelectedValuePath="ID" SelectedValue="{Binding Item1.ID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding Item1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<ComboBox x:Name="cmbCode2" ItemsSource="{Binding AllItems}" DisplayMemberPath="ID" SelectedValuePath="ID" SelectedValue="{Binding Item1.ID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding Item1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<ComboBox x:Name="cmbCode3" ItemsSource="{Binding AllItems}" DisplayMemberPath="ID" SelectedValuePath="ID" SelectedValue="{Binding Item1.ID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding Item1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<ComboBox x:Name="cmbCode4" ItemsSource="{Binding AllItems}" DisplayMemberPath="ID" SelectedValuePath="ID" SelectedValue="{Binding Item1.ID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding Item1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
I have four TextBoxes corresponding to these four Comboboxes as such:
<TextBlock x:Name="txtName1" Text="{Binding Item1.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName2" Text="{Binding Item2.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName3" Text="{Binding Item3.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock x:Name="txtName4" Text="{Binding Item4.Name,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
What i want is that the user should never be able to select the same ID from more than one combobox.
Is there some simple way that could be done,especially using xaml only?How can i hide or show the items selected/unselected from other comboboxes so that the user can't select the same ID from more than one combobox ever?
So far i have tried to send the selected Item and the entire List to a MultivalueConverter and eliminating/adding items to the Lists there itself,but this seems too meesy.Any other better idea would be appreciated.
You could have a separate list for each of your ComboBoxes. You could then add a LostFocus event handler to each of them. You could use this to repopulate the lists for the other ComboBoxes to exclude the selection.
For example, if I've got 5 items in my list; initially I'll be able to select all 5 in any of my ComboBoxes. When I select Item1 in ComboBox1 the LostFocus event handler will update the lists behind ComboBoxes 2-4 to remove Item1. When I then select Item2 in ComboBox2 the LostFocus event handler will then update the lists behind ComboBoxes 3 and 4 to remove Item2. And so on...
An alternative approach might be to let the user select whatever they like and then run some kind of validation on the selected values to make sure that they're unique. This article goes through some of your options.
Personally, I'd go with the second approach; perhaps with a message above the textboxes indicating that the selection must be unique. You could indicate any errors and block any actions that rely on the selection while it's invalid but you're not having to update your data constantly which will probably lead to a smoother UI.
You can use the code to hide the selected item in different combobox
for (int count = 0; count <= cmb1.Items.Count -1; count++)
{
if((ComboBoxItem)(cmb1.Items[count])).SelectedValue==TextBox1.Text)
((ComboBoxItem)(cmb1.Items[count])).Visibility = System.Windows.Visibility.Collapsed;
}
This code you can write in selected event of the comboxes.
I guess you can write the same logic using triggers in XAML
You should handle this kind of logic in your view models. Here is an example for you that should give you the idea:
View Model:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
AllItems = new List<Item>() { new Item { Name = "1" }, new Item { Name = "2" }, new Item { Name = "3" }, new Item { Name = "4" } };
}
public List<Item> AllItems { get; set; }
private Item _item1;
public Item Item1
{
get { return _item1; }
set
{
_item1 = value;
NotifyPropertyChanged();
if (value != null)
value.CanSelect = false;
}
}
private Item _item2;
public Item Item2
{
get { return _item2; }
set
{
_item2 = value;
NotifyPropertyChanged();
if (value != null)
value.CanSelect = false;
}
}
private Item _item3;
public Item Item3
{
get { return _item3; }
set
{
_item3 = value; NotifyPropertyChanged();
if (value != null)
value.CanSelect = false;
}
}
private Item _item4;
public Item Item4
{
get { return _item4; }
set
{
_item4 = value;
NotifyPropertyChanged();
if (value != null)
value.CanSelect = false;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Item : INotifyPropertyChanged
{
public int ID { get; set; }
public string Name { get; set; }
private bool _canSelect = true;
public bool CanSelect
{
get { return _canSelect; }
set { _canSelect = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
XAML:
<Style x:Key="icstyle" TargetType="ComboBoxItem">
<Setter Property="IsEnabled" Value="{Binding CanSelect}" />
</Style>
...
<ComboBox x:Name="cmbCode1" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item1}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>
<ComboBox x:Name="cmbCode2" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item2}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>
<ComboBox x:Name="cmbCode3" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item3}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>
<ComboBox x:Name="cmbCode4" ItemsSource="{Binding AllItems}" SelectedItem="{Binding Item4}" DisplayMemberPath="Name" ItemContainerStyle="{StaticResource icstyle}"/>
I am looking for a way to know if my listview contains a value. Below is my code.
public class OnlineUserList
{
public string Name { get; set; }
public string Color { get; set; }
}
<ListView x:Name="lvOnlineUsers" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SelectionMode="Single" SelectionChanged="lvOnlineUsers_SelectionChanged">
<ListView.View>
<GridView x:Name="lvOnlineUsersGridView" AllowsColumnReorder="False">
<GridViewColumn Header="Online Users" Block.TextAlignment="Center" TextOptions.TextFormattingMode="Display" TextBlock.FontWeight="Bold">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Name="tbOnlineUsersGridView" Text="{Binding Path=Name}" Foreground="{Binding Path=Color}" HorizontalAlignment="Center" VerticalAlignment="Center" TextOptions.TextFormattingMode="Display" Style="{StaticResource ResourceKey=lblLabel}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
public void AddUserToList(string username)
{
lvOnlineUsers.Items.Add(new OnlineUserList { Name = username, Color = "Black" });
}
Now this is where am having issue
public void RemoveUserFromList(string username)
{
if(lvOnlineUsers.Items.Contains(username))
lvOnlineUsers.Items.Remove(username);
}
You should learn MVVM.
In the mean time, put the items in an ObservableCollection and assign it to the listview's ItemsSource property in your codebehind. Thereafter, repeat after me: Never, ever touch lvOnlineUsers.Items. Never, never, never. Forget that it exists. Everything you do, you interact with the ObservableCollection. Search it, add items to it, remove items from it. The UI will magically and mysteriously update itself.
I'm going to assume this is in MainWindow. If this is in a different view, the constructor will have a different name.
public MainWindow()
{
InitializeComponent();
lvOnlineUsers.ItemsSource = _onlineUsers;
}
private ObservableCollection<OnlineUserList> _onlineUsers
= new ObservableCollection<OnlineUserList>();
public void AddUserToList(string username)
{
_onlineUsers.Add(new OnlineUserList { Name = username, Color = "Black" });
}
public void RemoveUserFromList(string username)
{
// We don't search _onlineUsers for the string username, because
// _onlineUsers doesn't contain strings. It contains your user class.
// So instead, we look for the user class instance that has the name
// we want.
var found = _onlineUsers.FirstOrDefault(ou => ou.Name == username);
if (found != null)
{
_onlineUsers.Remove(found);
}
}
Until you have looked into MVVM, try this:
for(int i = lvOnlineUsers.Items.Count - 1; i >= 0; --i)
{
OnlineUserList item = lvOnlineUsers.Items[i] as OnlineUserList;
if (item != null && item.Name == username)
lvOnlineUsers.Items.Remove(lvOnlineUsers.Items[i]);
}
Goal is to have multiple Combobox, once the item is selected in any of the Combobox, it should be removed or hided from other Comboboxes for selection.
I'm able to change the source whenever the selection got changed on any of the Comboboxes. But Problem is when I remove the selected item from the ItemsSource, item got removed from all the sources including the one on which I selected.
Here is the sample
xaml
<StackPanel>
<ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
<ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
<ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
<ComboBox Width="100" Height="50" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ComboboxItems}" />
</StackPanel>
Codebehind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ObservableCollection<string> s = new ObservableCollection<string>();
s.Add("item1");
s.Add("item2");
s.Add("item3");
s.Add("item4");
s.Add("item5");
s.Add("item6");
DataContext = new MainViewModel() { ComboboxItems = s , SelectedItem = "item2" };
}
}
public class MainViewModel : INotifyPropertyChanged
{
private ObservableCollection<string> comboboxitems;
public ObservableCollection<string> ComboboxItems
{
get { return comboboxitems; }
set { comboboxitems = value; OnPropertyChanged("ComboboxItem"); }
}
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
comboboxitems.Remove(value); //here removing selected item from itemssource
OnPropertyChanged("SelectedItem");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propname)
{
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propname));
}
}
I know I can have multiple Collection for each Combobox but that may take lot of memory if number of Combobox increases.
Hope, there should be a easy way to achieve this in WPF.
You could define different SelectedItem for each ComboBox, and then create a wrapper of the SharedItemSource for each ComboBoxto filter out the SelectedItem of other ComboBox. eg:
C# :
public IEnumerable<string> ComboboxItems1
{
get
{
return ComboboxItems.Where(x => x != SelectedItem2 && x != SelectedItem3);
}
}
public string SelectedItem1
{
get { return _selectedItem1; }
set
{
if (_selectedItem1 != value)
{
_selectedItem1 = value;
RaisePropertyChanged("SelectedItem1");
RaisePropertyChanged("ComboboxItems2"); //raise propertychanged to refresh GUI
RaisePropertyChanged("ComboboxItems3");
}
}
}
public IEnumerable<string> ComboboxItems2
{
get
{
return ComboboxItems.Where(x => x!=SelectedItem1&&x!=SelectedItem3);
}
}
public string SelectedItem2
{
get { return _selectedItem2; }
set
{
if (_selectedItem2 != value)
{
_selectedItem2 = value;
RaisePropertyChanged("SelectedItem2");
RaisePropertyChanged("ComboboxItems1"); //raise propertychanged to refresh GUI
RaisePropertyChanged("ComboboxItems3");
}
}
}
public IEnumerable<string> ComboboxItems3
{
get
{
return ComboboxItems.Where(x => x != SelectedItem1 && x != SelectedItem2);
}
}
public string SelectedItem3
{
get { return _selectedItem3; }
set
{
if (_selectedItem3 != value)
{
_selectedItem3 = value;
RaisePropertyChanged("SelectedItem3");
RaisePropertyChanged("ComboboxItems1"); //raise propertychanged to refresh GUI
RaisePropertyChanged("ComboboxItems2");
}
}
}
XAML:
<ComboBox SelectedItem="{Binding SelectedItem1}" ItemsSource="{Binding ComboboxItems1}" />
<ComboBox SelectedItem="{Binding SelectedItem2}" ItemsSource="{Binding ComboboxItems2}" />
<ComboBox SelectedItem="{Binding SelectedItem3}" ItemsSource="{Binding ComboboxItems3}" />
I am having problem binding ObservableCollection as ItemsSource to a combo box (this combobox is in a listview of having some rows).
I followed A collection of StackPanel as ItemsSource of ComboBox but I did not get any clues for resolving my problem.
Problem:
I was able to add items to a combobox which is at the top on the form.
I have created a listview containing 3 text blocks and 1 combobox.
I am successful in populating data for the text blocks in listview.
But the problem lies with Combobox. First time, it shows all the items for each row in ListView. Once I select item or click on the combobox again to see the items, my list disappears. Only one combobox in the listview row shows all items. Other comboboxes shows blank.
Also, I was trying to save the index of the selected item and show the selected panel next time. But I did not get how to bind the stackpanel with selecteditem and selecteditemvalue.
I tried many ways of directly binding the items to the combobox in listview. But nothing worked. Request someone to help me on this.
Details of the code is given below:
I have XAML like below:
<Grid>
<Grid Height="40">
<ComboBox x:Name="cbList" />
</Grid>
<Grid Margin="0,56,0,168"></Grid>
<ListView x:Name="lvFirst" Margin="0,195,0,12">
<ListView.View>
<GridView >
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Width="50" x:Uid="tbListView1" Text="{Binding FirstName}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Width="50" x:Uid="tbListView2" Text="{Binding LastName}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Width="50" x:Uid="tbListView1" Text="{Binding ID}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox Width="100" x:Uid="cbListView" ItemsSource="{Binding Path=SPForComboBox}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
In the code behind I have a Contact class as below:
public class Contact : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
void Notify(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
private string _fn;
private string _ln;
public string FirstName
{
get
{ return _fn; }
set
{ _fn = value; Notify("FirstName"); }
}
public string LastName
{
get
{ return _ln; }
set
{ _ln = value; Notify("LastName"); }
}
private int _id;
public int ID
{
get { return _id; }
set { _id = value; Notify("ID"); }
}
public StackPanel sp;
public override string ToString()
{
return FirstName + " " + LastName;
}
private ObservableCollection<StackPanel> _sp;
public ObservableCollection<StackPanel> SPForComboBox
{
get { return _sp; }
set { _sp = value; Notify("SPForComboBox"); }
}
}
To populate cbList Items, I am repeatedly calling below function after Initialization() function:
private void AddColours(string name, byte hexcolor)
{
//Add this ShiftType to Combo box
SolidColorBrush rectangleBrush = new SolidColorBrush();
Color color = new Color();
color.A = hexcolor;
rectangleBrush.Color = color;
System.Windows.Controls.StackPanel stkPanel = new StackPanel(); //stack panel to hold rectangle + text
stkPanel.Orientation = Orientation.Horizontal;
cbList.Items.Add(stkPanel);
Rectangle colorRect = new Rectangle(); //rectangle showing colour for shift
colorRect.Height = 12;
colorRect.Width = colorRect.Height;
colorRect.Fill = rectangleBrush;
stkPanel.Children.Add(colorRect);
System.Windows.Controls.TextBlock cboText = new TextBlock(); //Name of shift
cboText.Text = name;
cboText.Margin = new Thickness(5, 5, 5, 5);
stkPanel.Children.Add(cboText);
}
In the main window class, I have a created an ObservableCollection object as public static (object name is contacts).
public static ObservableCollection<Contact> contacts = new ObservableCollection<Contact>();
After the Initialization() function, I am populating contacts as below:
AddColours("First", 100);
AddColours("Second", 50);
AddColours("Third", 20);
AddColours("Fourth", 0);
AddColours("Fifth", 80);
Contact c1 = new Contact();
c1.FirstName = "Digo";
c1.LastName = "Maradona";
c1.ID = 0;
c1.SPForComboBox = new ObservableCollection<StackPanel>();
foreach (StackPanel sp in cbList.Items)
{
c1.SPForComboBox.Add(sp);
}
Contact c2 = new Contact();
c2.FirstName = "Brian";
c2.LastName = "Lara";
c2.ID = 1;
c2.SPForComboBox = new ObservableCollection<StackPanel>();
foreach (StackPanel sp in cbList.Items)
{
c2.SPForComboBox.Add(sp);
}
Contact c3 = new Contact();
c3.FirstName = "Sachin";
c3.LastName = "Tendulkar";
c3.ID = 2;
c3.SPForComboBox = new ObservableCollection<StackPanel>();
foreach (StackPanel sp in cbList.Items)
{
c3.SPForComboBox.Add(sp);
}
contacts.Add(c1);
contacts.Add(c2);
contacts.Add(c3);
lvFirst.ItemsSource = contacts;
HighCore, Thank you very much for the links. I have existing implementation and adding combobox to that.
I too felt that the method followed is not good. I shall certainly look at the alternatives provided by you and suggested by pushpraj.
Answer:
I thought referring objects in other combobox will work till the items exist in that combobox. But I need to create rectangle and textblock for reach combobox I am creating and for each entry in that combobox.
So certainly I need to do it in foreach loop.
Also, once I do this I can use SelectedIndex referring to the integer and SelectedItem to sp (individual stackpanel in that class).
This method is not good to follow but might be helpful for somebody.
Thanks.