WPF TabItem Style screws up the control positions - c#

I created a new TabItem Style which looks the way I wanted. But now it screws up the positions of all the controls which are placed on the TabItem. It moves them from the top left area to the right bottom area of the TabItem. Any help would be highly appreciated. (Yes, I am sure I need the style in C# NOT in XAML)
var functionReturnValue = new Style();
ControlTemplate L_NewControlTemplate = new ControlTemplate(typeof(TabItem));
FrameworkElementFactory L_ElemFactory = new FrameworkElementFactory(typeof(Border));
L_ElemFactory.SetBinding(Border.FocusVisualStyleProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("FocusVisualStyle") });
L_ElemFactory.SetBinding(Border.BackgroundProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("Background") });
L_ElemFactory.SetBinding(Border.BorderBrushProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("BorderBrush") });
L_ElemFactory.SetBinding(Border.BorderThicknessProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("BorderThickness") });
//L_ElemFactory.SetValue(Border.CornerRadiusProperty, new CornerRadius(0,12,0,0));
L_ElemFactory.SetValue(Border.SnapsToDevicePixelsProperty, true);
FrameworkElementFactory L_ContentPresenter = new FrameworkElementFactory(typeof(ContentPresenter));
L_ContentPresenter.SetValue(ContentPresenter.ContentSourceProperty, "Header");
L_ContentPresenter.SetBinding(ContentPresenter.HorizontalAlignmentProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("HorizontalContentAlignment") });
L_ContentPresenter.SetBinding(ContentPresenter.VerticalAlignmentProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("VerticalContentAlignment") });
L_ContentPresenter.SetBinding(ContentPresenter.SnapsToDevicePixelsProperty, new System.Windows.Data.Binding { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent, Path = new PropertyPath("SnapsToDevicePixels") });
L_ElemFactory.AppendChild(L_ContentPresenter);
L_NewControlTemplate.VisualTree = L_ElemFactory;
Trigger NewTrigger;
//Trigger IsEnabled = true
NewTrigger = new Trigger { Property = TabItem.IsEnabledProperty, Value = true };
NewTrigger.Setters.Add(new Setter(TabItem.ForegroundProperty, F_Foreround));
NewTrigger.Setters.Add(new Setter(TabItem.BackgroundProperty, F_Background));
L_NewControlTemplate.Triggers.Add(NewTrigger);
//Trigger MouseOver
NewTrigger = new Trigger { Property = TabItem.IsMouseOverProperty, Value = true };
NewTrigger.Setters.Add(new Setter(TabItem.ForegroundProperty, F_Foreround));
NewTrigger.Setters.Add(new Setter(TabItem.BackgroundProperty, F_MouseOver));
L_NewControlTemplate.Triggers.Add(NewTrigger);
//Trigger Selected
NewTrigger = new Trigger { Property = TabItem.IsSelectedProperty, Value = true };
NewTrigger.Setters.Add(new Setter(TabItem.ForegroundProperty, F_Foreround));
NewTrigger.Setters.Add(new Setter(TabItem.BackgroundProperty, F_Background));
L_NewControlTemplate.Triggers.Add(NewTrigger);
//Trigger Selected
NewTrigger = new Trigger { Property = TabItem.IsSelectedProperty, Value = false };
NewTrigger.Setters.Add(new Setter(TabItem.BackgroundProperty, L_IsDeActive));
L_NewControlTemplate.Triggers.Add(NewTrigger);
functionReturnValue.Setters.Add(new Setter(TabItem.FocusVisualStyleProperty, null));
functionReturnValue.Setters.Add(new Setter(TabItem.BackgroundProperty, F_Background));
functionReturnValue.Setters.Add(new Setter(TabItem.BorderBrushProperty, Brushes.Green));
functionReturnValue.Setters.Add(new Setter(TabItem.BorderThicknessProperty, new Thickness(0)));
functionReturnValue.Setters.Add(new Setter(TabItem.ForegroundProperty, F_Foreround));
functionReturnValue.Setters.Add(new Setter(TabItem.HorizontalContentAlignmentProperty, System.Windows.HorizontalAlignment.Center));
functionReturnValue.Setters.Add(new Setter(TabItem.VerticalContentAlignmentProperty, System.Windows.VerticalAlignment.Center));
functionReturnValue.Setters.Add(new Setter(TabItem.PaddingProperty, new Thickness(0)));
functionReturnValue.Setters.Add(new Setter(TabItem.MarginProperty, new Thickness(-4, -4, 0, 0)));
functionReturnValue.Setters.Add(new Setter(TabItem.TemplateProperty, L_NewControlTemplate));
return functionReturnValue;

So it turns out your first problem is these two lines:
functionReturnValue.Setters.Add(new Setter(TabItem.HorizontalContentAlignmentProperty, System.Windows.HorizontalAlignment.Center));
functionReturnValue.Setters.Add(new Setter(TabItem.VerticalContentAlignmentProperty, System.Windows.VerticalAlignment.Center));
Just omit those; they're acting on the tab item content, not on the header.
To restyle the header, you have a lot of options.
This will put a 20 unit margin around your content presenter:
L_ContentPresenter.SetValue(ContentPresenter.MarginProperty, new Thickness(20));
20's pretty arbitrary; of course you can use your own values. This will give it 20 unit side margins and 10 unit top/bottom margins:
L_ContentPresenter.SetValue(ContentPresenter.MarginProperty, new Thickness(20, 10, 20, 10));
You could also put a Border or something inside the header control template, surrounding the ContentPresenter, and do something with the padding or margins of that containing control. This kind of thing is infinitely easier to work with in XAML, so I'm not going to the trouble of doing that in C#.
You could have the TabItem style set HeaderTemplate, which is a DataTemplate:
var headerTemplate = new DataTemplate();
var label = new FrameworkElementFactory(typeof(Label));
label.SetBinding(Label.ContentProperty, new Binding());
label.SetValue(Label.MarginProperty, new Thickness(16, 12, 16, 12));
headerTemplate.VisualTree = label;
functionReturnValue.Setters.Add(new Setter(TabItem.HeaderTemplateProperty, headerTemplate));
In closing, I'd like to reiterate that whatever you need to do at runtime to Styles, you can do more easily and far more maintainably in XAML than in C#.

Related

How to dynamically create data template and bind treeview hierarchical data in code behind C#

I have a scenario, where a treeview changes its data template and data binding definition dynamically.
I created a treeview in XAML like this:
<TreeView x:Name="BimTreeView">
</TreeView>
I didn't defined the data template and binding definition in XAML. Because the data template and binding definition must have to be changed by user's preference.
I tried the following C# code that I found here to create the data template definition dynamically. However, looking at the following code, I couldn't figure out how to change data binding definition via C# code.
private DataTemplate GetHeaderTemplate()
{
//create the data template
DataTemplate dataTemplate = new DataTemplate();
//create stack pane;
FrameworkElementFactory stackPanel = new FrameworkElementFactory(typeof(StackPanel));
stackPanel.Name = "parentStackpanel";
stackPanel.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
// Create check box
FrameworkElementFactory checkBox = new FrameworkElementFactory(typeof(CheckBox));
checkBox.Name = "chk";
checkBox.SetValue(CheckBox.NameProperty, "chk");
checkBox.SetValue(CheckBox.TagProperty, new Binding());
checkBox.SetValue(CheckBox.MarginProperty, new Thickness(2));
checkBox.SetValue(CheckBox.TagProperty, new Binding() { Path = new PropertyPath("Name") });
stackPanel.AppendChild(checkBox);
// Create Image
FrameworkElementFactory image = new FrameworkElementFactory(typeof(Image));
image.SetValue(Image.MarginProperty, new Thickness(2));
image.SetBinding(Image.SourceProperty, new Binding() { Path = new PropertyPath("ImageUrl") });
stackPanel.AppendChild(image);
// create text
FrameworkElementFactory label = new FrameworkElementFactory(typeof(TextBlock));
label.SetBinding(TextBlock.TextProperty, new Binding() { Path = new PropertyPath("Name") });
label.SetValue(TextBlock.ToolTipProperty, new Binding());
stackPanel.AppendChild(label);
//set the visual tree of the data template
dataTemplate.VisualTree = stackPanel;
return dataTemplate;
}
I would really appreciate if someone could explain how can I change the data template and bind treeview hierarchical data in code behind C#.
Thank you!!
Here's the remedy to the above code. The following code can now dynamically bind and can dynamically create datatemplate for the treeview in wpf.
public static void FillTree()
{
BIMExplorerUserControl.Instance.BimTreeView.ItemTemplate = GetTemplate();
BIMExplorerUserControl.Instance.BimTreeView.ItemsSource = ViewModel.Instance.DefaultExplorerView;
}
public static HierarchicalDataTemplate GetTemplate()
{
//create the data template
HierarchicalDataTemplate dataTemplate = new HierarchicalDataTemplate();
//create stack pane;
FrameworkElementFactory stackPanel = new FrameworkElementFactory(typeof(StackPanel));
stackPanel.Name = "parentStackpanel";
stackPanel.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
////// Create check box
FrameworkElementFactory checkBox = new FrameworkElementFactory(typeof(CheckBox));
checkBox.Name = "chk";
checkBox.SetValue(CheckBox.NameProperty, "chk");
checkBox.SetValue(CheckBox.TagProperty, new Binding());
checkBox.SetValue(CheckBox.MarginProperty, new Thickness(2));
checkBox.SetValue(CheckBox.TagProperty, new Binding() { Path = new PropertyPath("Name") });
stackPanel.AppendChild(checkBox);
// create text
FrameworkElementFactory label = new FrameworkElementFactory(typeof(TextBlock));
label.SetBinding(TextBlock.TextProperty, new Binding() { Path = new PropertyPath("Name") });
label.SetValue(TextBlock.MarginProperty, new Thickness(2));
label.SetValue(TextBlock.FontWeightProperty, FontWeights.Bold);
label.SetValue(TextBlock.ToolTipProperty, new Binding());
stackPanel.AppendChild(label);
dataTemplate.ItemsSource = new Binding("Elements");
//set the visual tree of the data template
dataTemplate.VisualTree = stackPanel;
return dataTemplate;
}

Combobox in TemplateColumn fill RowHeight

I create my DataGridTemplateColumn with a ComboBox inside in my Code. When I change the Height of my DataGridRow I want the ComboBox to always fill the Cell. But as it is now my ComboBox always stays the same Height. It works with the Width though. Here is what I have tried so far:
(For Information the whole code)
ItemsPanelTemplate IPT = null;
DataGridTemplateColumn DGTC = new DataGridTemplateColumn();
DataTemplate DataTMP = null;
Binding bind = new Binding(strPropertyname);
FrameworkElementFactory cboFactory = new FrameworkElementFactory(typeof(ComboBox));
cboFactory.SetValue(ComboBox.HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
cboFactory.SetValue(ComboBox.VerticalAlignmentProperty, VerticalAlignment.Stretch);
cboFactory.SetValue(ComboBox.ItemsSourceProperty, DTCBOSource.DefaultView);
cboFactory.SetValue(ComboBox.IsEditableProperty, false);
cboFactory.SetValue(ComboBox.IsTextSearchEnabledProperty, true);
cboFactory.SetValue(ComboBox.IsEnabledProperty, !blnIsReadOnly);
cboFactory.SetValue(ComboBox.SelectedValuePathProperty, DTCBOSource.Columns[0].ColumnName);
cboFactory.SetValue(ComboBox.DisplayMemberPathProperty, DTCBOSource.Columns[1].ColumnName);
Binding bHeight = new Binding();
bHeight.Source = _DGSource;
bHeight.Path = new PropertyPath("RowHeight");
bHeight.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
cboFactory.SetValue(ComboBox.HeightProperty, bHeight);
cboFactory.AddHandler(ComboBox.GotFocusEvent, new RoutedEventHandler(DG_EditingElementEnter));
cboFactory.AddHandler(ComboBox.LostFocusEvent, new RoutedEventHandler(DG_EditingElementLeave));
IPT = (ItemsPanelTemplate)(Application.Current.TryFindResource("CBOVirtualPanel"));
if (IPT != null)
{
cboFactory.SetValue(ComboBox.ItemsPanelProperty, IPT);
}
bind.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
bind.NotifyOnTargetUpdated = true;
//bind.Mode = BindingMode.TwoWay;
cboFactory.SetBinding(ComboBox.SelectedValueProperty, bind);
DataTMP = new DataTemplate();
DataTMP.VisualTree = cboFactory;
DGTC.CellTemplate = DataTMP;
DGTC.SortMemberPath = strPropertyname;
//_DGSource.TargetUpdated += DG_CellValueChanged_Event;
return DGTC;

Coding4Fun InputPrompt style text box

I'm trying to style the Coding4Fun InputPrompt control to set a border on the textbox element and change the unselected colour in code.
I've not been able to find any examples, and visual studio doesn't recognise the control properly (InputPrompt is displayed in red with no intellisense, but the project runs fine).
I've managed to set some colours and update the buttons, but no success on the textbox.
Can anyone point me in the right direction please?
Here is what I have so far:
var input = new InputPrompt
{
Title = "Title",
Message = "My Message",
IsCancelVisible = true,
Background = new SolidColorBrush(Color.FromArgb(0xCC, 0x00, 0x00, 0x00)),
Foreground = new SolidColorBrush(Colors.White)
};
input.Completed += input_Completed;
input.InputScope = new InputScope
{
Names = {new InputScopeName() {NameValue = InputScopeNameValue.TelephoneNumber}}
};
foreach (var button in input.ActionPopUpButtons)
{
button.Foreground = new SolidColorBrush(Colors.White);
button.BorderBrush = new SolidColorBrush(Colors.White);
button.Margin = new Thickness(0,5,0,0);
}
input.BorderThickness = new Thickness(5.0);
input.Show();

How can i display chart from code behind in windows phone

I create a chart in my windows phone app.this is my code XAML
<amq:SerialChart x:Name="line" DataSource="{Binding results}" CategoryValueMemberPath="month"
AxisForeground="White"
PlotAreaBackground="Black"
GridStroke="DarkGray" >
<amq:SerialChart.Graphs>
<amq:LineGraph Title="Sales" ValueMemberPath="actual" Brush="red" StrokeThickness="5" />
</amq:SerialChart.Graphs>
</amq:SerialChart>
How can i write this XAML with c# (code behind only)
How can i write this XAML with c# (code behind only)
In general this is usually not a good idea. But if you must, you would use something along these lines:
var chart = new SerialChart
{
CategoryValueMemberPath = "month",
AxisForeground = new SolidColorBrush(Colors.White),
PlotAreaBackground = new SolidColorBrush(Colors.Black),
GridStroke = new SolidColorBrush(Colors.DarkGray)
};
chart.SetBinding(SerialChart.DataSourceProperty, new Binding("results"));
var lineGraph = new LineGraph
{
Title = "Sales",
ValueMemberPath = "actual",
Brush = new SolidColorBrush(Colors.Red),
StrokeThickness = "5"
};
chart.Graphs.Add(lineGraph);
Then you would just need to add the chart to the page/container using for example stackPanel.Children.Add(chart).
var chart = new SerialChart
{
CategoryValueMemberPath = "month",
AxisForeground = new SolidColorBrush(Colors.White),
PlotAreaBackground = new SolidColorBrush(Colors.Black),
GridStroke = new SolidColorBrush(Colors.DarkGray)
};
chart.SetValue(SerialChart.DataSourceProperty, new Binding("results"));
var lineGraph = new LineGraph
{
Title = "Sales",
ValueMemberPath = "actual",
Brush = new SolidColorBrush(Colors.Red),
StrokeThickness = 5
};
chart.Graphs.Add(lineGraph);

Datatemplate in c# code-behind

I search an option to build a datatemplate in c# code.
I had used :
DataTemplate dt = new DataTemplate(typeof(TextBox));
Binding bind = new Binding();
bind.Path = new PropertyPath("Text");
bind.Mode = BindingMode.TwoWay;
FrameworkElementFactory txtElement = new FrameworkElementFactory(typeof(TextBox));
txtElement.SetBinding(TextBox.TextProperty, bind);
txtElement.SetValue(TextBox.TextProperty, "test");
dt.VisualTree = txtElement;
textBox1.Resources.Add(dt, null);
But it doesn't work (it is placed at the Loaded-Method of the window - so my textbox should show the word "test" at window start). Any idea?
Each element needs to be added to the current visual tree. For example:
ListView parentElement; // For example a ListView
// First: create and add the data template to the parent control
DataTemplate dt = new DataTemplate(typeof(TextBox));
parentElement.ItemTemplate = dt;
// Second: create and add the text box to the data template
FrameworkElementFactory txtElement =
new FrameworkElementFactory(typeof(TextBox));
dt.VisualTree = txtElement;
// Create binding
Binding bind = new Binding();
bind.Path = new PropertyPath("Text");
bind.Mode = BindingMode.TwoWay;
// Third: set the binding in the text box
txtElement.SetBinding(TextBox.TextProperty, bind);
txtElement.SetValue(TextBox.TextProperty, "test");

Categories