Change DataTemplate for Expander header from Code Behind - c#

I am attempting to add an expander from code behind to an existing ListBox. The content that needs to be displayed in the header of the expander comes from a directory name which may or may not contain underscores. I want to preserve the directory name and not have the first underscore be interpreted as a keyboard shortcut.
I found this thread discussing how to do it in xaml and have tried to implement the same solution in code behind without any luck.
I also found this thread discussing how to create a data template from the code behind, but I can't get that to work either.
I have tried the following code snippets but either it won't compile or it just displays blanks for the expander headers:
String markup = String.Empty;
markup = "<TextBlock text=\"" + directory.Name + "\"/>";
ex.HeaderTemplate = new DataTemplate((DataTemplate)XamlReader.Load(markup));
.
ex.HeaderTemplate = new DataTemplate("TextBlock");
TextBlock tb = new TextBlock();
tb.Text = directory.Name;
ex.Header = tb;

you don't need to change HeaderTemplate to avoid underscore conversion into AccessKey.
add TextBlock into Expander.Header explicitly, and it will keep text unchanged.
<Expander>
<Expander.Header>
<TextBlock x:Name="ExpanderHeader"/>
</Expander.Header>
</Expander>
this way you don't need to create UI elements in c# code.
change header text in ExpanderHeader textBlock
ExpanderHeader.Text = directory.Name;
or bind it if there is a view model:
<TextBlock x:Name="ExpanderHeader" Text="{Binding Path=...}"/>

Related

How to add a column of textboxes to a ListView w/ GridView in C# - WPF dymanically?

I've got a ListView defined in XML:
<ListView
x:Name="lvFuellmengenDetails"
HorizontalAlignment="Center"
Height="570"
FontSize="30"
Margin="10,85,10,0"
VerticalAlignment="Top"
HorizontalContentAlignment="Center"
Width="572">
In the code behind I set the GridView as a view to the ListView to be able to add some columns
var gridView = new GridView();
this.lvFuellmengenDetails.View = gridView;
gridView.Columns.Add(new GridViewColumn
{
Header = "Nummer",
Width = 200,
DisplayMemberBinding = new Binding("Nummer")
});
gridView.Columns.Add(new GridViewColumn
{
Header = "Wert",
Width = 200,
DisplayMemberBinding = new Binding("Wert")
});
I need another Column that should be editable in every line (e.g. Textboxes) - defined not in XML, but in C# code)
If that is not possible: is there a way to detect a certain line is clicked?
I looked for an Event like "ItemClicked" but couldnt find any.
Then I could open a DialogBox and change the label instead of using textboxes. Thanks for your help.
To archive what you want, you have to either build the DataTemplate or get the resource and assign that onto the columns ItemTemplate
it is more or less the same as if you would use normal XAML
as the DataTemplate probably wont change, you probably want to create the DataTemplate in XAML and then just load it from the resources

Create controltemplate in code, how to specify the converter in the binding

I checked these answers, but none had the information I'm looking for:
How to setup a WPF datatemplate in code for a treeview?
How to set Control Template in code?
Create ControlTemplate programmatically in WPF
Here is the gist of my code:
DataGridTextColumn col = new DataGridTextColumn();
Style styl = null;
// Need to add this on a per-column basis
// <common:RequiredPropertyDisplayBrushConverter x:Key="requiredDisplayBrushConverter" />
string xaml = "<ControlTemplate TargetType=\"{x:Type DataGridCell}\"> <TextBox Background=\"{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content.Text, Converter={StaticResource requiredDisplayBrushConverter} > </TextBox> </ControlTemplate>";
MemoryStream sr = new MemoryStream(Encoding.ASCII.GetBytes(xaml));
ParserContext pc = new ParserContext();
pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
ControlTemplate ct = (ControlTemplate)XamlReader.Load(sr, pc);
styl.Setters.Add(new Setter(TemplateProperty, ct));
col.CellStyle = styl;
In the ControlTemplate, a binding refers to the converter mentioned in the comments. When the converter is defined in the xaml as a resource for the DataGrid, I get a runtime error: {"Cannot find resource named 'requiredDisplayBrushConverter'. Resource names are case sensitive."}
Can I add this as a resource to the column? Or add it to the DataGrid's resources at runtime?
Or is there some other technique?
Thanks --
You can add it to the xaml but you'll need to rearrange it. The resource will need to be defined before you can use it. Which means the background will need to be defined as a child tag.
Change your xaml to this:
string xaml = "<ControlTemplate TargetType=\"{x:Type DataGridCell}\"><TextBox><TextBox.Resources><common:RequiredPropertyDisplayBrushConverter x:Key=\"requiredDisplayBrushConverter\" /></TextBox.Resources><TextBox.Background><Binding RelativeSource=\"{RelativeSource TemplatedParent}\" Path=\"Content.Text\" Converter=\"{StaticResource requiredDisplayBrushConverter}\"/></TextBox.Background></TextBox></ControlTemplate>";
And you'll need to define the common namespace. Add this after your other namespaces (with the correct namespace/assembly, of course):
pc.XmlnsDictionary.Add("common", "clr-namespace:WPFApplication;assembly=WPFApplication");
OR, you could just add the resource to your App.xaml, if that is an option.

Add XAML programmatically in Windows Phone

I need to add programmatically some UI.
In order to do that I am creating each single Object and adding it to my main grid.
This way (I need to do that in a lambda function):
Deployment.Current.Dispatcher.BeginInvoke(() => {
StackPanel stkpanel = new StackPanel();
stkpanel.Orientation = Orientation.Horizontal;
TextBlock textBlock = new TextBlock();
textBlock.Text = "text1";
Grid myGrid = new Grid();
myGrid.Children.Add(textBlock);
MainPage currentPage = (MainPage)(((App)Application.Current).RootFrame.Content as PhoneApplicationPage);
currentPage.LayoutRoot.Children.Add(myGrid);
...
});
Is there a way to add to my MainPage.xaml another File.xaml and display the result?
I am using silverlight 8.1
Thanks
There some different ways to do that.
UserControl
One way is to create a user Control and use it direct in XAML or instantiate it in the code behind like a standard control. You can find a template in the Add Item dialog in Visual Studio.
Pages
It is also possible to create a second page and Display them in a Frame tag. It is possible in XAML and code behind. Here is an example:
<Frame Margin="0,148,0,0" Name="myFrame"/>
myFrame.Navigate(typeof(BlankPage1));
XamlReader
If you have a partial XAML code, stored in a file you can parse it manual and add the objects to the page. Your XAML must look like the following with the xmlns Attribut
<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Button Content="BTN 1" />
<Button Content="BTN 2" />
<Button Content="BTN 3" />
</StackPanel>
Then you can parse it with XamlReader:
var uri = new Uri("ms-appx:///test.xaml");
var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
var panel = XamlReader.Load(await FileIO.ReadTextAsync(file)) as StackPanel;
root.Children.Add(panel);
Be sure you set the Build Action of the XAML file to Content, if you will use it as an resource. You can also pass directly a string with XAML code to the XamlReader.Load function.

Disabled TextBox Style

I have created a TextBox above a Path-Element (the Path Element draws a rectangular thing, which acts as the design of the textbox). Now I want to disable this TextBox with
valCon.ValueTextBox.IsEnabled = false;
This works so far. However, since I don't want the TextBox to have any Style (no Color, no Borders, etc.), but only a visible Text in it, I'm getting a small problem:
When the TextBox is disabled, it automatically receives a style which I can't get rid of. The Background changes to white, the Opacity changes to around 0.3 and Borders appear.
I can't seem to solve this problem by adding
valcon.ValueTextBox.Background = new SolidColorBrush(Colors.Transparent);
valcon.ValueTextBox.BorderBrush = new SolidColorBrush(Colors.Transparent);
etc.
It just seems to ignore this. Does anyone know a solution?
Greetings
Narakuvera
You need to take control over the template to achieve the same
here is a basic template for you with no border and no background TextBox
<TextBox Text="hello">
<TextBox.Template>
<ControlTemplate TargetType="TextBox">
<ScrollViewer Margin="0"
x:Name="PART_ContentHost" />
</ControlTemplate>
</TextBox.Template>
</TextBox>
you can choose to set IsEnabled="False" and it will still remain border less
Code behind approach
ControlTemplate ct = new ControlTemplate(typeof(TextBox));
FrameworkElementFactory sv = new FrameworkElementFactory(typeof(ScrollViewer));
sv.Name = "PART_ContentHost";
ct.VisualTree = sv;
textbox1.Template = ct;
WinRT code behind approach
string template = "<ControlTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" TargetType=\"TextBox\"><ScrollViewer Name=\"PART_ContentHost\" /></ControlTemplate>";
ControlTemplate сt = (ControlTemplate)XamlReader.Load(template);
textbox1.Template = сt;

Using RichTextBlock in FlipView in Metro Style App

I am using standard Visual Studio templates and I have a ItemsDetailPage that contains a FlipView with a RichTextBlock in its DataTemplate.
I want to set the RichTextBlock block to my custom Paragraphs generated in text. I think there is no way to bind RichTextBlocks Block in XAML so I am using code behind. In the Loaded event of RichTextBlock I set its Block, that works ok. But the problem is, the Loaded event gets called only once when the page is displayed. When I "flip" to another item, the selected item of the FlipView changes but the Loaded event does not get called again (I think this is ok).
I tried setting the RichTextBlock in the FlipViews SelectionChanged item but that does not work.
var ind = this.flipView.SelectedIndex;
var flipViewItem = this.flipView.ItemContainerGenerator.ContainerFromIndex(flipView.SelectedIndex);
if (flipViewItem != null)
{
var scroller = FindFirstElementInVisualTree<ScrollViewer>(flipViewItem);
var tb = scroller.FindDescendantByName("richTextColumns").FindDescendantByName("richTextBlock") as RichTextBlock;
SetRichContent(tb, (flipView.SelectedItem as ArticleViewModel).HtmlContent);
}
The SetRichContent gets called, sets the RichTextBlocks Blocks but visually they do not change and after a few flips, the whole app crashes without any additional information.
So my question is, how do I get my own code called on the RichTextBlock with each flip (seleced item change)?
You can bind rich text boxes. Make sure your data context is set properly. We need to see more code to make an appropriate answer.
<RichTextColumns>
<RichTextColumns.ColumnTemplate>
<DataTemplate>
<RichTextBlockOverflow Width="400" Margin="50,0,0,0"/>
</DataTemplate>
</RichTextColumns.ColumnTemplate>
<RichTextBlock Width="400">
<Paragraph>
<Run Text="{Binding Content}"/>
</Paragraph>
</RichTextBlock>
</RichTextColumns>

Categories