In xaml when I want to add some behavior I do like this:
<!-- XAML -->
<TabItem behaviors:TabItemValidationBehavior.ActivateValidation ="True">
<TabItem.Header>
<TextBlock Text="Header"
Foreground="{Binding Path=(behavior:TabItemBehavior.Foreground), RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TabItem}}}" />
</TabItem.Header>
</TabItem>
It is possible to do the same programmatically?
// C#
TabItem tab = new TabItem();
??tab.AddBehavior(behaviors:TabItemValidationBehavior.ActivateValidation(True));??
??tab.Header= new TextBlock { Foreground.BindTo(behavior:TabItemBehavior.Foreground, tab) };??
How to achieve that?
Behavior exposes an AttachedProperty. You can set it like
TabItem tab = new TabItem();
TabItemValidationBehavior.SetActivateValidation(tab, true);
TextBlock text = new TextBlock();
Binding binding = new Binding();
binding.Path = new PropertyPath(TabItemBehavior.ForegroundProperty);
binding.RelativeSource = new RelativeSource{Mode = RelativeSourceMode.FindAncestor, AncestorType = typeof(TabItem)};
text.SetBinding(TextBlock.ForegroundProperty, binding);
tab.Header=text;
Related
I don't know How to name this, so I don't know what to google for, so I decided to ask here.
My XAML Code is:
<Expander ExpandDirection="Right">
<Expander.Header>
<TextBlock Text="PC and Notebook" RenderTransformOrigin=".5,.5">
<TextBlock.LayoutTransform>
<RotateTransform Angle="90" />
</TextBlock.LayoutTransform>
</TextBlock>
</Expander.Header>
<TreeView>
</TreeView>
</Expander>
So I want to make this XAML Code into Code-Behind (for a while loop).
I started simple with:
Expander cat_expander = new Expander();
cat_expander.ExpandDirection = ExpandDirection.Right;
And my problem now is. How to add <Expander.Header> dynamically ? How people name this thing when a Control has another control inside it?
I hope u can understand what I mean.
You set the Header property to a TextBlock:
Expander cat_expander = new Expander();
cat_expander.ExpandDirection = ExpandDirection.Right;
TextBlock textBlock = new TextBlock();
textBlock.Text = "PC and Notebook";
textBlock.RenderTransformOrigin = new Point(0.5, 0.5);
textBlock.LayoutTransform = new RotateTransform() { Angle = 90 };
cat_expander.Header = textBlock;
cat_expander.Content = new TreeView();
I'm experimenting with code-behind created WPF masks as prototype for a WPF mask designer.
In my ViewModel i have a DataTable and a DataView (which is simply the DefaultView of the DataTable).
In my DataTable i got two columns ("vorname" and "nachname") and four rows.
In my WPF mask i want to have a DataGrid and two TextBoxes, which are binded to the SelectedItem of the DataGrid and the columns (either "vorname" or "nachname").
When i select an item in the DatGrid at runtime, the data from that item shall be showed in the TextBoxes.
First i tried to define the DataGrid in the XAML file and generate the TextBoxes an their bindings in code.
Here it works fine.
I select an item in the DataGrid and the data of the item is showed in the TextBoxes.
But when i generate the grid in code, it doesn't work anymore.
Is there some sort of NotifyOnSelectedIndexChanged, that i'm missing?
Any help will be appreciated.
This is the XAML:
<Window x:Class="DesignerTest.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow"
Height="400"
Width="600">
<DockPanel x:Name="mainpanel">
<!--<DataGrid x:Name="datagrid"
DockPanel.Dock="Top"
Height="120" />-->
<WrapPanel x:Name="wrappanel">
<!--<TextBox x:Name="vornameSelected" Width="150" Margin="5" Text="{Binding SelectedItem.vorname, ElementName=datagrid}" IsEnabled="False" />
<TextBox x:Name="nachnameSelected" Width="150" Margin="5" Text="{Binding SelectedItem.nachname, ElementName=datagrid}" IsEnabled="False" />-->
<!--<TextBox x:Name="vornameSelected" Width="150" Margin="5" IsEnabled="False" />
<TextBox x:Name="nachnameSelected" Width="150" Margin="5" IsEnabled="False" />-->
</WrapPanel>
</DockPanel>
</Window>
And this is the code for creating and binding:
// The ViewModel und the DataTable are created.
_vm = new SerializingTestViewModel();
_vm.CreateDataTable();
this.DataContext = _vm.DataTable;
// The DataGrid and it's Binding are created.
DataGrid datagrid = new DataGrid();
datagrid.Name = "datagrid";
DockPanel.SetDock(datagrid, Dock.Top);
datagrid.Height = 120;
datagrid.ItemsSource = _vm.DataSource;
mainpanel.Children.Add(datagrid);
// The Textboxes and the Bindings are created.
TextBox vornameSelected = new TextBox();
vornameSelected.Name = "vornameSelected";
vornameSelected.Width = 150;
Thickness margin = new Thickness(5);
vornameSelected.SetValue(TextBox.MarginProperty, margin);
vornameSelected.IsEnabled = false;
Binding selectedItemBinding = new Binding();
selectedItemBinding.ElementName = "datagrid";
selectedItemBinding.Path = new PropertyPath("SelectedItem.vorname");
vornameSelected.SetBinding(TextBox.TextProperty, selectedItemBinding);
wrappanel.Children.Add(vornameSelected);
TextBox nachnameSelected = new TextBox();
nachnameSelected.Name = "nachnameSelected";
nachnameSelected.Width = 150;
margin = new Thickness(5);
nachnameSelected.SetValue(TextBox.MarginProperty, margin);
nachnameSelected.IsEnabled = false;
selectedItemBinding = new Binding();
selectedItemBinding.ElementName = "datagrid";
selectedItemBinding.Path = new PropertyPath("SelectedItem.nachname");
nachnameSelected.SetBinding(TextBox.TextProperty, selectedItemBinding);
wrappanel.Children.Add(nachnameSelected);
Try setting your binding source using the Source property instead of ElementName
//selectedItemBinding.ElementName = "datagrid"
selectedItemBinding.Source = datagrid;
The problem might be that the ElementName lookup for items is not working as expected because items are added dynamically at runtime via code behind.
I'd like to create a tabcontrol through code with 2 tabs . I used the code below :
TabControl tb = new TabControl();
tb.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
tb.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
tb.VerticalContentAlignment = System.Windows.VerticalAlignment.Stretch;
tb.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Stretch;
ressource_design.initialiserTabControl(tb);
tb.Margin = new Thickness(10, 10, 10, 10);
TabItem ti1 = new TabItem();
ti1.Header = ServicesLangue.RM.GetString("CONTENU_ACCUEIL_LISTE_SAS");
ti1.Content = _listeSAS;
tb.Items.Add(ti1);
TabItem ti2 = new TabItem();
ti2.Header = ServicesLangue.RM.GetString("CONTENU_ACCUEIL_TBSM");
ti2.Content = _tbsm;
tb.Items.Add(ti2);
this.DockPrincipal.Children.Add(tb);
But the height of my tabitem is the height of the children control. This is driving me crazy !
I've tried to add the code below in my child control:
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Grid}}, Path=ActualHeight}"
But this makes le child control too big !
Note: I have the same problem with the Accordion.
Thanks
Remove any static Height and Width you set in XAML or Code behind.
HorizontalContentAlignment and VerticalContentAlignment are by default set to Stretch.
If your DockPrincipal is a Dockpanel and is filling your whole form, you could set LastChildFill="True"
Is it possible put an user control inside a doument viewer? If possible, how will it be that?
You can use the following..
Edit
Added a Grid which binds its Width/Height to the FixedPage ActualWidth/ActualHeight to achieve centering
<DocumentViewer>
<FixedDocument>
<PageContent>
<FixedPage HorizontalAlignment="Center">
<Grid Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type FixedPage}},
Path=ActualWidth}"
Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type FixedPage}},
Path=ActualHeight}">
<local:MyUserControl HorizontalAlignment="Center"/>
</Grid>
</FixedPage>
</PageContent>
</FixedDocument>
</DocumentViewer>
Unfortunately the Visual Studio 2010 designer is broken here and you'll get a message saying "Property 'pages' does not support values of type 'PageContent`.
This is reported here: WPF FixedDocument object doesn't allow PageContent children
As a workaround you can load it in code behind
Xaml
<DocumentViewer>
<FixedDocument Loaded="FixedDocument_Loaded"/>
</DocumentViewer>
Code behind
private void FixedDocument_Loaded(object sender, RoutedEventArgs e)
{
FixedDocument fixedDocument = sender as FixedDocument;
MyUserControl myUserControl = new MyUserControl();
myUserControl.HorizontalAlignment = HorizontalAlignment.Center;
myUserControl.VerticalAlignment = VerticalAlignment.Center;
Grid grid = new Grid();
grid.Children.Add(myUserControl);
FixedPage fixedPage = new FixedPage();
fixedPage.Children.Add(grid);
Binding widthBinding = new Binding("ActualWidth");
widthBinding.Source = fixedPage;
Binding heightBinding = new Binding("ActualHeight");
heightBinding.Source = fixedPage;
grid.SetBinding(Grid.WidthProperty, widthBinding);
grid.SetBinding(Grid.HeightProperty, heightBinding);
PageContent pageContent = new PageContent();
(pageContent as IAddChild).AddChild(fixedPage);
fixedDocument.Pages.Add(pageContent);
}
I need to create a DataGridColumn from code.
The XAML equivalent would be:
<data:DataGridTemplateColumn Header="Name" Width="100">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" TextTrimming="WordEllipsis"></TextBlock>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
I've started like that:
DataGridTemplateColumn column = new DataGridTemplateColumn
{
Header = "Name",
Width = 100,
};
TextBlock inside = new TextBlock {TextTrimming = TextTrimming.CharacterEllipsis};
But I don't know how to 'merge' such puzzles. There are nested elements in XAML, how to achieve this from code?
A good way to do this is to pack the entire XAML snippet into a string and call XamlReader.Load() or XamlReader.Parse() on it. The bonus feature of this approach is that it'll work in Silverlight as well (with some fiddling), where you can't build DataTemplates in code.
Almost there, change your code to this and it should work:
DataGridTemplateColumn column = new DataGridTemplateColumn
{
Header = "Name",
Width = 100,
};
FrameworkElementFactory ftb = new FrameworkElementFactory(typeof(TextBlock));
Binding b = new Binding("Name");
ftb.SetValue(TextBlock.Text, b);
ftb.SetValue(TextBlock.TextTrimming, TextTrimming.CharacterEllipsis);
DataTemplate ct = new DataTemplate();
ct.VisualTree = ftb;
column.CellTemplate = ct;
Another method besides the above is to define your datatemplate in XAML within your resources then dynamically load it in the code:
XAML:
<Window.Resources>
<DataTemplate x:Key="myCellTemplate">
<TextBlock Text="{Binding Name}" TextTrimming="WordEllipsis" />
</DataTemplate>
</Window.Resources>
Code:
DataGridTemplateColumn column = new DataGridTemplateColumn
{
Header = "Name",
Width = 100,
};
column.CellTemplate = this.FindResource("myCellTemplate") as DataTemplate;