Binding ComboBox (source) with Buttons not working properly. - c#

Hello I am binding 16 buttons to combobox, but I have problem that it works as it should only when window is loaded, then when i pick new color from ComboBox, background of buttons don't change.
This is how I am binding (Shape1Color is said combobox):
for (int i = 0; i < Shape1.Children.Count; i++)
{
Binding btnbinding = new Binding();
btnbinding.Converter = new ButtonColorConverter();
btnbinding.Source = Shape1Color.SelectedItem;
btnbinding.NotifyOnSourceUpdated = true;
(Shape1.Children[i] as Button).SetBinding(Button.BackgroundProperty, btnbinding);
}
So it only works when window loads, but then when i choose new item from combobox it doesn't enter my converter and I don't know why.

try use Shape1Color as binding Source and set SelectedItem as Path for binding
Binding btnbinding = new Binding();
btnbinding.Converter = new ButtonColorConverter();
btnbinding.Source = Shape1Color;
btnbinding.Path = new PropertyPath("SelectedItem");
btnbinding.NotifyOnSourceUpdated = true;
setting btnbinding.Source = Shape1Color.SelectedItem; works but only once. It doesn't change when SelectedItem changes

Related

WPF - DataGridColumn Width not Returning Expected Value

.NET4.0 : I'm building a DataGrid in a codebehind, so I'm not using any XAML. C# only. When the user right clicks anywhere in the column header, I want to show a context menu. Here's some code to give you an idea:
public void MakeAllColumns()
{
for (int i = 0; i < AllColumnDisplayNames.Length; i++)
{
// create a new column depending on the data to be displayed
DataGridTextColumn col = new DataGridTextColumn();
col.MaxWidth = 300;
// create a new Textblock for column's header and add it to the column
TextBlock headerText = new TextBlock() { Text = AllColumnDisplayNames[i] };
col.Header = headerText;
/// create a new context menu and add it to the header
ContextMenu menu = new ContextMenu();
headerText.ContextMenu = menu;
// build the context menu depending on the property
menu.Items.Add(new Button() { Content = "FOOBAR" });
// add the bindings to the data
col.Binding = new Binding(AllColumnBindings[i]);
AllColumns.Add(AllColumnDisplayNames[i], col);
}
}
The problem with this approach is that the user needs to click on the actual TextBox in order to activate the context menu, as opposed to anywhere on the header.
As I can't think of a way to make the TextBox fill the header width, all I can think to do is change the TextBox width property to bind to the column's width. The columns stretch to fit their content, and as such they have different widths. However, when I print all the columns ActualWidth properties to console, it says that they all have width 20, which is not what my GUI looks like. How can I get the column width that corresponds to how it looks in my GUI?
To you solve your problem must exchange o your body method by this body:
This code was tested:
for (int i = 0; i < AllColumnDisplayNames.Length; i++)
{
// create a new column depending on the data to be displayed
DataGridTextColumn col = new DataGridTextColumn();
col.MaxWidth = 300;
/// create a new context menu
ContextMenu menu = new ContextMenu();
// build the context menu depending on the property
menu.Items.Add(new Button() { Content = "FOOBAR" });
// create a new column's header and add it to the column
DataGridColumnHeader head = new DataGridColumnHeader() { Content = AllColumnBindings[i] };
head.ContextMenu = menu;//add context menu to DataGridColumnHeader
col.Header = head;
// add the bindings to the data
col.Binding = new Binding(AllColumnBindings[i]);
AllColumns.Add(AllColumnDisplayNames[i], col);
}
Instead of using TextBlock I used DataGridColumnHeader, which has the ContextMenu property, thus occupying all the space (height and width) of the Header.

WPF CheckBox checked event on scrolling thought datagrid

I have a datagrid with a DataGridTemplateColumn containing a CheckBox. I create the column like this:
DataGridTemplateColumn cTemplateColumn = new DataGridTemplateColumn();
cTemplateColumn.Header = "Auswahl";
FrameworkElementFactory cFactory = new FrameworkElementFactory(typeof(CheckBox));
Binding b1 = new Binding("[__intern_cv__]");
//b1.IsAsync = true;
b1.Converter = new StringToBoolConverter(this);
b1.Mode = BindingMode.TwoWay;
b1.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
cFactory.SetValue(CheckBox.IsCheckedProperty, b1);
cFactory.SetValue(CheckBox.HorizontalAlignmentProperty, HorizontalAlignment.Center);
cFactory.AddHandler(CheckBox.CheckedEvent, new RoutedEventHandler(CheckedEvent));
cFactory.AddHandler(CheckBox.UncheckedEvent, new RoutedEventHandler(CheckedEvent));
cFactory.AddHandler(CheckBox.PreviewMouseDownEvent, new MouseButtonEventHandler(checkBoxMouseDown));
DataTemplate cCellTemplate = new DataTemplate();
cCellTemplate.VisualTree = cFactory;
cTemplateColumn.CellTemplate = cCellTemplate;
Columns.Add(cTemplateColumn);
Now i have the problem, that during scrolling throught the DataGrid, the CheckedEvent is called, with Checked == False.
The vents a subscripted here:
cFactory.AddHandler(CheckBox.CheckedEvent, new RoutedEventHandler(CheckedEvent));
cFactory.AddHandler(CheckBox.UncheckedEvent, new RoutedEventHandler(CheckedEvent));
How can scrolling call the event?
maybe someone has an idea, thank you!
By default the DataGrid virtualizes its rows. This means that during scrolling old rows are re-used with new data. If the new data has "[__intern_cv__]" set to false, while the previous data had it set to true an Unchecked event will be raised.

How do you set binding of ComboBox ItemsSource in UserControl?

Here is the combobox in my UserControl:
<Combobox ItemsSource="{Binding ComboItemsProperty}" />
I have tried:
Binding bind = new Binding();
bind.Mode = BindingMode.OneWay;
bind.Source = this;
bind.Path = new PropertyPath("ComboItemsProperty");
this.SetBinding(ComboBox.ItemsSourceProperty, bind);
However, this doesn't work. I think I am doing the bind.Source wrong, but I'm not sure what to set the Source to. This code is inside my UserControl.xaml.cs.
You can try (Replace this)
Binding bind = new Binding();
bind.Mode = BindingMode.OneWay;
bind.Source = yourCollectionSourceOrClass; //<--Replace with your collection
bind.Path = new PropertyPath("ComboItemsProperty");
this.SetBinding(ComboBox.ItemsSourceProperty, bind);
You need to the set context of the instance containing your property ComboItemsProperty. So instead of 'this' u should set it to 'this.DataContext' or other class object instance containing the ItemSource property you have defined..
Try this,
Binding bind = new Binding();
bind.Mode = BindingMode.OneWay;
bind.Source = this.DataContext;
bind.Path = new PropertyPath("ComboItemsProperty");
this.SetBinding( ComboBox. ItemsSource Property, bind);
(posting frm mobile)
I have tried a lot of ways to do this, however, nothing seems to work.
I am instead going to serialize the binding when the .xaml file gets saved out. This seems to be working perfectly. Binding will no longer have to be set in code.

Creating a custom styled WPF Checkbox purely in the code behind

I'm trying to create a custom CheckBox control which will ideally be represented by a blue cross, which turns a lighter shade of blue when the mouse Mouse-Over event occurs, and fires a Click event when clicked.
I've seen ways of doing this in the XAML code using Control Templates and Styles, but not for purely in the code behind. I've created custom Styles in the code before and applied them well enough, but I'm having trouble with the amount of customization required this time around e.g replacing the whole checkbox with an image of a blue cross.
Does anybody know a standard way of a doing this? Can you create a full templated style in the XAML code, and then reference that template when setting the Properties on your new checkbox object in the code behind?
Thanks in advance.
I hate to do this, as it ruins the declaration approach with XAML, but there are times that you need to do it.
That being said, take a look at the FrameworkElementFactory class to build your XAML. It's a pretty neat pattern. The following snippet shows where I created a DataTemplate for a ListView in code. I needed to dynamically add elements based on the number of days in a month for a time reporting application.
GridView gv = new GridView();
int i = 0;
foreach (string s in vm.DateList)
{
string column = string.Format("DisplayTime[{0}].Hours", i);
DataTemplate dt = new DataTemplate();
DateTime date = DateTime.Parse(s);
bool isWeekday = true;
if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday)
{
isWeekday = false;
}
Binding binding = new Binding();
binding.Path = new PropertyPath(column);
binding.Mode = BindingMode.TwoWay;
FrameworkElementFactory gridElement = new FrameworkElementFactory(typeof(Grid));
gridElement.SetValue(Grid.WidthProperty, 60.0);
gridElement.SetValue(Grid.HeightProperty, 94.0);
gridElement.SetValue(Grid.MarginProperty, new Thickness(0.0, 0.0, 0.0, 4.0));
if (!isWeekday)
{
gridElement.SetValue(Grid.BackgroundProperty, new SolidColorBrush(Color.FromRgb(65, 65, 65)));
}
FrameworkElementFactory txtelement = new FrameworkElementFactory(typeof(TextBox));
txtelement.SetBinding(TextBox.TextProperty, binding);
txtelement.SetValue(TextBox.WidthProperty, 40.0);
txtelement.SetValue(TextBox.HeightProperty, 20.0);
txtelement.SetValue(TextBox.VerticalAlignmentProperty, VerticalAlignment.Center);
txtelement.SetValue(TextBox.HorizontalAlignmentProperty, HorizontalAlignment.Center);
txtelement.SetValue(TextBox.TextAlignmentProperty, TextAlignment.Right);
gridElement.AppendChild(txtelement);
dt.VisualTree = gridElement;
gv.Columns.Add(new GridViewColumn()
{
Header = s,
// DisplayMemberBinding = new Binding(column),
CellTemplate = dt
});
i++;
}
ETCListView.View = gv;

ToolStripComboBox.SelectedItem change does not propagate to binding source

My binding is set up as this:
_selectXAxisUnitViewModelBindingSource = new BindingSource();
_selectXAxisUnitViewModelBindingSource.DataSource = typeof(SelectXAxisUnitViewModel);
_selectedUnitComboBoxBindingSource = new BindingSource();
_selectedUnitComboBoxBindingSource.DataSource = _selectXAxisUnitViewModelBindingSource;
_selectedUnitComboBoxBindingSource.DataMember = "AvailableUnits";
_selectedUnitComboBox.ComboBox.DataSource = _selectedUnitComboBoxBindingSource;
_selectedUnitComboBox.ComboBox.DisplayMember = String.Empty;
_selectedUnitComboBox.ComboBox.ValueMember = String.Empty;
_selectedUnitComboBox.ComboBox.DataBindings.Add("SelectedItem",
_selectXAxisUnitViewModelBindingSource,
"SelectedUnit", true, DataSourceUpdateMode.OnPropertyChanged);
// this is a bug in the .Net framework: http://connect.microsoft.com/VisualStudio/feedback/details/473777/toolstripcombobox-nested-on-toolstripdropdownbutton-not-getting-bindingcontext
_selectedUnitComboBox.ComboBox.BindingContext = this.BindingContext;
The property "AvailableUnits" is a collection of strings and the "SelectedUnit" is a string-property. Now the dropdown list is populated as expected, but when I select and item in the list, the change is not propagated to the binding source. Any idea what I am doing wrong?
Update:
I Created a little test project and this problem occurs when I add a ToolStripComboBox as a subitem of another ToolStripItem. If I add the ToolStripItem directly to the MenuStrip everything works fine. The BindingContext is not assigned to the ToolStripComboBox when added as a sub item (see my code-comment) and my fix doesn't seem to do whats necessary to get this to work.
Can you change
_selectXAxisUnitViewModelBindingSource.DataSource = typeof(SelectXAxisUnitViewModel);
To
_selectXAxisUnitViewModelBindingSource.DataSource = new SelectXAxisUnitViewModel();

Categories