I have searched for a solution for a day and a half. Most examples that I get that explain / semi explain the situation relate to a combobox with "static" type items. I have the following structure.
DataModel Item
ObservableCollection CombinedData inside DataFilter class (i.e has other properties including "ParentName used for buttoncontent")
ObservableCollection Filters inside DataFilterGroup class
DataFilterGroup is 1 item in DataViewModel
So window's DataContext is DataViewModel.
I have a DataTemplate in which I would like to show the DataFilterGroup items from code behind
This is where I need help with please!!
so basically: ItemsControl's Itemsource is bound to DataFilterGroup
How do I bind a combobox in the DataFilter so that it's items source point to DataFilter. Therefore the source will change (or the content of the combobox will change with every DataFilterGroup Item).
I apologise if this is a repeat question. What I have up to now is the following (and have tried several ways to bind the combobox but no items appear. Supprisingly enough the Buttoncontent show up. Special combo is control deriverd from Combobox which is a button and combobox.
private static DataTemplate DataFilterTemplate
{
get
{
DataTemplate DFT = new DataTemplate();
DFT.DataType = typeof(DataFilters);
FrameworkElementFactory Stack = new FrameworkElementFactory(typeof(VirtualizingStackPanel));
Stack.SetValue(VirtualizingStackPanel.DataContextProperty, new Binding());
Stack.SetValue(VirtualizingStackPanel.OrientationProperty, Orientation.Horizontal);
FrameworkElementFactory Item = new FrameworkElementFactory(typeof(SpecialCombo));
//Item.SetValue(SpecialCombo.DataContextProperty, new Binding());
Item.SetValue(SpecialCombo.ButtonContentProperty, new Binding("ParentName"));
Binding b = new Binding("CombinedData");
//b.RelativeSource.AncestorType = typeof(ItemsControl);
Item.SetBinding(SpecialCombo.ItemsSourceProperty, b);
//Item.SetValue(SpecialCombo.ItemsSourceProperty, new Binding("CombinedData"));
Item.SetValue(SpecialCombo.DisplayMemberPathProperty, "FullName");
Item.SetValue(SpecialCombo.SelectedValuePathProperty, "Index");
Item.SetValue(SpecialCombo.SelectedValueProperty, "SelectedItem");
Item.SetValue(SpecialCombo.ToggleVisibleProperty, new Binding("ComboVisibility"));
//Item.SetValue(SpecialCombo.SelectedValueProperty, new Binding("SelectedItem"));
Stack.AppendChild(Item);
DFT.VisualTree = Item;
return DFT;
}
}
Child is ItemsControl
Child.ItemsSource = DVM.Filters.FullCollection;
Child.ItemTemplate = DataFilterTemplate;
Thanks to punker 76 in another post where I restructured the question (here -> Can one bind a combobox Itemssource from a datatemplate of a ItemsControl) slightly the following had to be done.
(1) The Object DataFilters had to change from [creation of Dependency Object]
public class DataFilters : INotifyPropertyChanged
// to
public class DataFilters : DependencyObject
(2) Observalbe collection should also change. so
public ObservableCollection<DataModel> CombinedData;
// should become
public static readonly DependencyProperty CombinedData= DependencyProperty.Register("CombinedData", typeof(ObservableCollection<DataModel>), typeof(DataFilters), new FrameworkPropertyMetadata());
//and
public ObservableCollection<DataModel> CombinedData
{
get { return (ObservableCollection<DataModel>)GetValue(CombinedDataProperty); }
set { SetValue(CombinedDataProperty, value); }
}
(3) The correct Binding in the DataTemplate then becomes
Item.SetBinding(SpecialCombo.ItemsSourceProperty, new Binding("CombinedData") );
These are all the major steps to take to get a combobox type object be databound in a DataTemplate
Related
I have a ListView and its ItemsSource.
ListView IList = new ListView();
IList.ItemsSource = _routine_names;
In order to customize the Data Template for each item I'm doing:
IList.ItemTemplate = new DataTemplate(()=>
{
Label Routine_Name = new Label(); // should be_routine_names
return new ViewCell
{
View = new StackLayout{
Children = {Routine_Name}
}
};
});
When I run this my ListView is displayed and the list items are indeed there (they have onclick handlers that work) but there is no text, which should be whatever is in _routine_names.
My question how do I get the Label in the DataTemplate to be items in _routine_names?
The reason I'm adding a DataTemplate is so I can add swipe to delete.
You can just use the built in TextCell for what you're trying to do. It has a bindable TextProperty and an optional DetailProperty if you want a smaller text line below the main one.
IList.ItempTemplate = new DataTemplate(()=>
{
var textCell = new TextCell();
textCell.ContextActions.Add(yourAction);
textCell.SetBinding(TextCell.TextProperty, ".");
return textCell;
}
IList.ItemsSource = _routine_names;
yourAction is of type MenuItem as seen here
Also, please notice that IList is a name of a class in System.Collection namespace so I'd use something else there.
I have a ObservableCollection<List<MessageView>> (MessageView is a custom class) I instantiate it that way
public ObservableCollection<List<MessageView>> _messagesView;
public ObservableCollection<List<MessageView>> messagesView {
get {
if (_messagesView == null) {
_messagesView = new ObservableCollection<List<MessageView>>();
}
return _messagesView;
}
set {
if (_messagesView != value) {
_messagesView = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(messagesView)));
}
}
}
This property is set on a Singleton
I want to bind one of the item collection to a datagrid it would look that way in xaml:
<xmlns:module="clr-namespace:Myproject.MyNameSpace;assembly=Myproject">
<DataGrid
Name="DataGrid_messages"
...
ItemsSource="{Binding messagesView[2], Source={x:Static module:Singleton.Instance}}"
>
This is working well that way but this is not what I want to do. I want to have the control of my index. So I have to do the binding in c# with my controller but I never found an example to bind with a special index.
Binding myBinding = new Binding("messagesView");
myBinding.Source = Singleton.Instance;
myBinding.Path = ??
DataGrid_messages.SetBinding(DataGrid.ItemsSourceProperty, myBinding);
Share your thought about this, is it possible? Or a better way to do it?
UPDATE
Additional change to do with Clemens Answer:
The binding is set with the internal list so it's it which should be ObservableCollection type:
public List<ObservableCollection<MessageView>> messagesView;
Provided that the index is fixed, creating the binding path in code behind could look like this:
myBinding.Path = new PropertyPath(string.Format("messagesView[{0}]", index));
I have a wpf application in which I need to customize a combobox to make it editable.
public class AutoCompleteFacturation: ComboBox
{
List<vue_fsign_fiche_signaletique> liste = new List<vue_fsign_fiche_signaletique>();
// [...]
ItemsSource = NewDataSource;
liste = NewDataSource.ToList<vue_fsign_fiche_signaletique>();
ComboBoxItem item = (ComboBoxItem)base.Items[0];
item.Background = System.Windows.Media.Brushes.AliceBlue;
}
I need to change the background of the first item ComboBoxItem item = (ComboBoxItem)base.Items[0]; ==> I get an exception indicates that the cast of vue_fsign_fiche_signaletique to ComboBoxItem is not possible.
So How can I fix this to coloriate the first item of the combobox ?
Thanks
The item you're getting is the one that is bound using DataSource (here of type vue_fsign_fiche_signaletique).
What you need is ComboBoxItem, which is a container. To get it, use ItemContainerGenerator.ContainerFromIndex(index) or ItemContainerGenerator.ContainerFromItem(item):
https://msdn.microsoft.com/library/ms750552(v=vs.90).aspx
You binded your ComboBox on your list.
So Items return a list of vue_fsign_fiche_signaletique
2 Possibilities :
foreach (vue_fsign_fiche_signaletique fiche in liste)
{
ComboBoxItem i = new ComboBoxItem();
i.Content = fiche.Text;
i.Background = System.Windows.Media.Brushes.AliceBlue;
base.Items.Add(i);
}
Or wrap your vue_fsign_fiche_signaletique in a View Model and use a IValueConverter
I am implementing dynamic drag and drop over multiple listboxes, where I need to figure out collection name at runtime.
What I mean -> when executing OnDrop event I have to either add item to an already existing collection (collection can have more than one member), or replace already existing item (in a collection that can only have one member). I want to do something like following:
var collection = (sender as System.Windows.Controls.ListBox).ItemsSource as IList;
if (collection.GetName() == "col_AllData")
{
//allow more than one member
}
else
{
//allow only one member
}
I could try to check typeof(), however all item sources are of the same type.
Any help would be appreciated.
I managed to do so by creating a new Dependency property:
public static readonly DependencyProperty AllowMultipleMembersProperty =
DependencyProperty.RegisterAttached("AllowMultipleMembers", typeof(bool), typeof(IP_ListBoxDragDropBehavior_New), new PropertyMetadata(new PropertyChangedCallback(OnAllowMultipleMembersPropertyChanged)));
and in my OnDrop event I check for the following:
bool? bMoreMembers = this.AssociatedObject.GetValue(AllowMultipleMembersProperty) as bool?;
We have a user control with a custom dependency property (DP). The DP is bound to an ObservableCollection.
When a new item is added to the collection programatically, the databinding does not update the target DP. Why? We think it's because, unfortunately, in our case the target is not a ListBox or ListView, but a Canvas. The DP, when changed or initialized, is supposed to draw a Shape (!) onto the Canvas, and the shape's position and size is bound to the collection item's two properties: WIDTH, LEFT.
Ideally we don't want to clear the Canvas and redraw all items just becasue one has been added (or deleted). But how?
So:
How can the custom DP take care of drawing the shape for the new collection item? What callback do we need, at what point in time does this have to happen, and what specific MetaDataOptions might there?
Also, are there any good resources out there concerning all these dependency property options. They are quite confusing. MSDN does not really help with what we're trying to do.
Thanks!
EDIT:
The ObservableCollection is like so:
public class Projects : ObservableCollection<Project>
{
//no ommitted code. this class really IS empty!
}
The DP is like so:
public class MyUserControl : UserContorl
{
public static readonly DependencyProperty... etc. typeof(Projects)
private static void OnProjectsChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MyUserControl u = d as MyUserControl;
CpProjectCollection projects = e.NewValue as CpProjectCollection;
u.Refresh(projects);
}
private void Refresh(CpProjectCollection projects)
{
foreach (CpProject p in projects)
{
//...add each project to the Canvas
ProjectContorl pc = new ProjectControl();
pc.Project = project;
Binding b = new Binding("StartTime");
b.Converter = new TimeSpanConverter();
b.Source = pc.Project;
b.Mode = BindingMode.TwoWay;
c.SetBinding(Canvas.LeftProperty, b);
//do the same for project duration
}
}
}
If you bind to ObservableCollection, you get the change notification if the collection is replaced with another collection, not when the collection's content is changed. So, you'll need to subscribe to CollectionChanged event in your code-behind.
If you subscribe to CollectionChanged, you can see which are the new/deleted items in your ObservableCollection. You can add a new shape for each new item and remove old shapes for deleted items.