Combobox binding not working when window is in grid container - wpf

I try to bind a list in ComboBox with this code :
var template = new DataTemplate();
var comboBoxFactory = new FrameworkElementFactory(typeof(ComboBox));
template.VisualTree = comboBoxFactory;
Binding b = new Binding();
b.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, this.GetType(), 1);
b.Path = new PropertyPath("DataContext");
comboBoxFactory.SetBinding(ComboBox.ItemsSourceProperty, b);
comboBoxFactory.SetBinding(ComboBox.SelectedItemProperty, new Binding("ClassRoom"));
It's working when I launch the window simply, like this :
winListOrgane ee = new winListOrgane();
ee.Show();
But when I try to put this window in a grid container, it's not working :
_currentWindow = (ModelPage)Activator.CreateInstance(pPage.GetType());
_currentWindow.SetParam(genParam);
_currentWindow.InitPage();
object content = _currentWindow.Content;
_currentWindow.Content = null;
_containerPage.Children.Add((UIElement)content);
What can I do to fix this problem?
Thanks
Best regards,
Frederic

It looks like it is your RelativeSource on the Binding. Since you are binding to a specific Window class - in this case it looks like GetType() will return typeof(winListOrgane). If you change that to typeof(Window), it should work:
b.RelativeSource =
new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Window), 1);

Related

Get the object created by new FrameworkElementFactory(typeof(T))

We are adding a DataGridTemplateColumn to a DataGrid, and populating the DGTC with a combobox created via
DataGridTemplateColumn dgtc = new DataGridTemplateColumn();
FrameworkElementFactory comboBoxFactory = new FrameworkElementFactory(typeof(ComboBox));
/* snip */
DataTemplate cellEditTemplate = new DataTemplate();
cellEditTemplate.VisualTree = comboBoxFactory;
dgtc.CellEditingTemplate = cellEditTemplate;
dgtc.SortMemberPath = string.Format($"{descr.BindingPropertyName}");
dgtc.Header = descr.BindingPropertyName;
Later, we need to change properties such as the TextSearch.TextPathProperty.
We get the CellEditingTemplate from the DataGridTemplateColumn; the question is, "How to access the CellEditingTemplate.VisualTree as a combobox"?
This code suggests that the VisualTree is a combobox:
var cellEditingTemplate = dgtc.CellEditingTemplate;
var propsVals = cellEditingTemplate.GetPropertyValues();
foreach (KeyValuePair<string, string> pair in propsVals)
{
Debug.WriteLine($"Key: {pair.Key} value: {pair.Value}");
}
Output:
Key: Type value: Windows.Controls.ComboBox
It appears there is no way to cast the VisualTree to ComboBox.
What am I overlooking?
Thanks --

WPF prevent TreeViewItem to inherit contextMenu from parent by code

I have the following code and I set explicite the ContextMenu from a TreeViewItem to null but it shows all the time the same ContextMenu as the treeviewitem parents! Is that a bug? and how can I solve that?
Tree.Items.Clear();
System.Windows.Controls.TreeViewItem ceo = new System.Windows.Controls.TreeViewItem() { Header = "CEO" };
System.Windows.Controls.TreeViewItem manager1 = new System.Windows.Controls.TreeViewItem() { Header = "Manager1" };
System.Windows.Controls.TreeViewItem manager2 = new System.Windows.Controls.TreeViewItem() { Header = "Manager2" };
System.Windows.Controls.TreeViewItem person1 = new System.Windows.Controls.TreeViewItem() { Header = "person1" };
System.Windows.Controls.TreeViewItem person2 = new System.Windows.Controls.TreeViewItem() { Header = "person2" };
manager1.Items.Add(person1);
manager2.Items.Add(person2);
ceo.Items.Add(manager1);
ceo.Items.Add(manager2);
Tree.Items.Add(ceo);
// context Menu
MenuItem menu1 = new MenuItem();
menu1.Header = "Menu1";
MenuItem menu2 = new MenuItem();
menu2.Header = "Menu2";
MenuItem menu3 = new MenuItem();
menu3.Header = "Menu3";
MenuItem menu4 = new MenuItem();
menu4.Header = "Menu4";
MenuItem menu5 = new MenuItem();
menu5.Header = "Menu5";
MenuItem menu6 = new MenuItem();
menu6.Header = "Menu6";
System.Windows.Controls.ContextMenu ceoMenu = new ContextMenu();
ceoMenu.Items.Add(menu1);
ceoMenu.Items.Add(menu2);
ceoMenu.Items.Add(menu3);
System.Windows.Controls.ContextMenu managerMenu = new ContextMenu();
managerMenu.Items.Add(menu4);
managerMenu.Items.Add(menu5);
ceo.ContextMenu = ceoMenu;
manager1.ContextMenu = managerMenu;
manager2.ContextMenu = managerMenu;
System.Windows.Controls.ContextMenu personMenu = new ContextMenu();
personMenu.Items.Add(menu6);
person1.ContextMenu = personMenu;
person2.ContextMenu = null;
It works fine to set it like:
System.Windows.Controls.ContextMenu nullMenu = new ContextMenu();
nullMenu.Visibility = Visibility.Hidden;
person1.ContextMenu = personMenu;
person2.ContextMenu = nullMenu;
It's not a bug. If you set breakpoint on ContextMenuOpening event for person2, you will see, that it doesn't fired at all.
After that you can try to set breakpoint on ContextMenuOpening event for manager2. It's fired and on person2 node, but only because TreeViewItem is ItemsControl.
In WPF Visualizer we can see that:
It's not a bug. It is logical behavior. For example, if user clicks at the column at DataGrid, then it always shows the same ContextMenu. So if you set ContextMenu to null, then it just replaces your context menu by base context menu.
So we can make a little trick. We just change state of visibility of your ContextMenu.
So to have the personal Visibility of ContextMenu, you should just create another state of Visibility(Hidden, Visible or Collapse) to your created ContextMenu.
System.Windows.Controls.ContextMenu personMenu = new ContextMenu();
personMenu.Items.Add(menu6);
personMenu.Visibility = System.Windows.Visibility.Hidden;
person1TVI.ContextMenu = personMenu;
person2TVI.ContextMenu = personMenu;

Change Lineseries thickness in WPFToolkit.Chart C#

I'm trying change the line thickness in a serie dinamically created, I need turn the line more thick.
Below, follow the code to bind the created serie on chart component. It works fine, but I tryed adapt this in this code and I had no sucess.
Please help, thanks.
Style style = new Style(typeof(LineDataPoint));
style.Setters.Add(new Setter(LineDataPoint.OpacityProperty, (double)(0.0)));
style.Setters.Add(new Setter(LineDataPoint.BackgroundProperty, dadosSerie.ColorSerie));
LineSeries lineSerie = new LineSeries()
{
Title = dadosSerie.SerieTitle,
IndependentValueBinding = new Binding("Key"),
DependentValueBinding = new Binding("Value"),
DependentRangeAxis = dadosSerie.EixoY,
DataPointStyle = style,
ItemsSource = dadosSerie.DataSerie,
};
chtGraficos.Series.Add(lineSerie);
Have you tried adding a Style for the serie's Polyline instead?
It seams the style for the LineDataPoint is actually for every point on the serie.
Here is a working sample of a chart fully created on code-behind. You just have to create a window named MainWindow and add a reference on the project to System.Windows.Controls.DataVisualization.Toolkit:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var valueList = new Dictionary<string, int>();
valueList.Add("Developer", 60);
valueList.Add("Misc", 20);
valueList.Add("Project Manager", 40);
var style = new Style(typeof(Polyline));
style.Setters.Add(new Setter(Polyline.StrokeThicknessProperty, 10d));
var series = new LineSeries
{
PolylineStyle = style,
ItemsSource = valueList,
DependentValuePath = "Value",
IndependentValuePath = "Key",
};
var lineChart = new Chart { Height = 254 };
lineChart.Series.Add(series);
var mainGrid = new Grid();
mainGrid.Children.Add(lineChart);
this.Content = mainGrid;
}
}

Add a bound ComboBox column to a DataGridColumn at runtime

I'd like to display a DataGrid which will contain data I've uploaded from a data source into a DataTable. The columns will be different each time and some will need to be represented using a ComboBox.
How do I go about setting the DataGridTemplateColumn for a column, that needs a ComboBox, at runtime?
Ok, this is the closest I've got with the help of #Meleak, almost there, just displaying the key rather than the value when the grid is not being edited.
public partial class MainWindow : Window
{
public Dictionary MyDictionary { get; set; }
public MainWindow()
{
InitializeComponent();
//Init Dictionary
this.MyDictionary = new Dictionary<int, string>();
this.MyDictionary.Add(1, "Value 1");
this.MyDictionary.Add(2, "Value 2");
this.MyDictionary.Add(3, "Value 3");
DataTable dt = new DataTable();
DataColumn column = new DataColumn("MyTypeId", typeof(int));
dt.Columns.Add(column);
DataRow newRow = dt.NewRow();
newRow["MyTypeId"] = 1;
dt.Rows.Add(newRow);
dataGrid.Columns.Add(GetNewComboBoxColumn("My Type", "MyTypeId", this.MyDictionary));
this.DataContext = dt;
}
public static DataGridTemplateColumn GetNewComboBoxColumn(string header,
string bindingPath,
object itemsSource)
{
DataGridTemplateColumn comboBoxColumn = new DataGridTemplateColumn();
comboBoxColumn.Header = header;
Binding textBinding = new Binding();
textBinding.Path = new PropertyPath(bindingPath);
FrameworkElementFactory textBlock = new FrameworkElementFactory(typeof(TextBlock));
textBlock.SetValue(TextBlock.MarginProperty, new Thickness(3, 3, 3, 3));
textBlock.SetBinding(TextBlock.TextProperty, textBinding);
FrameworkElementFactory comboBox = new FrameworkElementFactory(typeof(ComboBox));
comboBox.SetValue(ComboBox.MarginProperty, new Thickness(1, 1, 1, 1));
comboBox.SetBinding(ComboBox.TextProperty, textBinding);
comboBox.SetValue(ComboBox.SelectedValuePathProperty, "Key");
comboBox.SetValue(ComboBox.DisplayMemberPathProperty, "Value");
Binding itemsSourceBinding = new Binding();
itemsSourceBinding.Source = itemsSource;
comboBox.SetBinding(ComboBox.ItemsSourceProperty, itemsSourceBinding);
comboBoxColumn.CellTemplate = new DataTemplate();
comboBoxColumn.CellTemplate.VisualTree = textBlock;
comboBoxColumn.CellEditingTemplate = new DataTemplate();
comboBoxColumn.CellEditingTemplate.VisualTree = comboBox;
return comboBoxColumn;
}
}
Update
You can use a DataGridComboBoxColumn and set SelectedValueBinding to get it to work the way you want. So just change the method you have to this one and it should work
public DataGridColumn GetNewComboBoxColumn(string header,
string bindingPath,
object itemsSource)
{
DataGridComboBoxColumn comboBoxColumn = new DataGridComboBoxColumn();
comboBoxColumn.Header = header;
comboBoxColumn.SelectedValuePath = "Key";
comboBoxColumn.DisplayMemberPath = "Value";
Binding binding = new Binding();
binding.Path = new PropertyPath(bindingPath);
comboBoxColumn.SelectedValueBinding = binding;
Binding itemsSourceBinding = new Binding();
itemsSourceBinding.Source = itemsSource;
BindingOperations.SetBinding(comboBoxColumn, DataGridComboBoxColumn.ItemsSourceProperty, itemsSourceBinding);
return comboBoxColumn;
}

WPF Binding a Dynamically Added Control

I am adding a to the "Company" RibbonApplicationMenuItem in my RibbonWindow with the following code:
var reset = DataContext as ICompanies;
if (reset != null)
{
// ToDo: Create interface to populate the mymenutems
var mymenuitems = new List<string>();
foreach (var item in mymenuitems)
{
var newbutton = new Button { Margin = new Thickness(2), Content = item };
MenuItem_Company.Items.Add(newbutton);
}
}
My XAML looks like this:
<ribbon:RibbonApplicationMenu ToolTipTitle="Application Menu">
<ribbon:RibbonApplicationMenuItem
Header="Company"
x:Name="MenuItem_Company"
ImageSource="Images\LargeIcon.png">
</ribbon:RibbonApplicationMenuItem>
</ribbon:RibbonApplicationMenu>
How do I bind my new button in code when I add it to the MenuItem_Company? I need it to bind to a property in my datacontext.
Thanks,
Eroc
var newbutton = new Button { Margin = new Thickness(2), Content = item };
Binding b = new Binding();
b.Source = reset;
b.Path = new PropertyPath("SomePropertyOnDataContext");
newButton.SetBinding(Button.IsEnabledProperty, b);
Varying assumptions in the code...but it should give you an idea where to start...

Resources