I have not been able to find a clean solution to the following problem even though there are a few related questions already on SO.
If I have a data template that is being used multiple times, for example, a TreeViewItem.HeaderTemplate, how can I change something the template for only some of the TreeViewItems.
For example, let's say my TVI HeaderTemplate has a textblock and depending on the string, I want to make the fontweight bold.
I want to do something like this:
((TextBlock)myTreeView.Items.ElementAt(0).FindName("myTextBlock")).FontWeight = FontWeights.Bold;
Does anyone have a solution for this? --> Thanks Evan
Edit: Is there a way to write a generic function to get a control based on it's name even if it's in a data template?
LayoutRoot.FindName("myTextBlock"); would work if myTextBlock was not in a datatemplate. How can I write a findElementInDataTemplate(string elementName, string parentName) function?
The reason Evan's answer is not what I'm looking for is because I am developing a control. I want the application developer who uses my control to be able to change any element in the control. If I use Evan's solution, that would require the application developer to have access to all the templates in the control. Possible, but not ideal. Thanks!
One way I have accomplished this is to store all the needed items in a class-level collection variable by using the Loaded event of the control. Take this DataTemplate for example.
<DataTemplate>
...
<TextBlock Loaded="TemplateTextBlock_Loaded" />
</DataTemplate>
Then you use the Loaded event to load up some sort of collection for later use.
private List<TextBlock> templateTextBlocks = new List<TextBlock>();
private void TemplateTextBlock_Loaded(object sender, RoutedEventArgs e)
{
TextBlock tb = sender as TextBlock;
if (!this.templateTextBlocks.Contains(tb)) this.templateTextBlocks.Add(tb);
}
Of course, if you're going to be loading and unloading the control, this may not work well for you.
If you're using data binding, have you tried using a binding converter? In this case you would do something like...
FontWeight={Binding Path=TextProperty, Converter={StaticResource BoldConverter}}
And the converter would be along the lines of...
string myTestString = (string)value;
if (myTestString.Contains("Bob"))
return FontWeights.Bold;
return FontWeights.Normal;
Which makes it less painful to try and root through the elements to locate a particular one.
My first reaction to such a requirement would be: are you really sure you want to be doing that? I would normally urge developers to look at the existing control patterns being used. In this case what you seem a Templated control would seem warranted.
Of course this doesn't provide the flexibility you are after. What you seem to be after is the "holy grail" of customisable controls, the desire to tweak any minor detail about the control without having to duplicate the entire template of the control. OF course this isn't really possible declaratively, if it were I'd dread the syntax and semantic rules that would govern it.
Having said that there are always exceptions. So I'll present a possible option despite feeling that you shouldn't be doing this.
This old answer provides a Descendents extension method allow you to enumerate controls across the object tree. Given an instance of a TreeViewItem you should be able to find the TextBlock you are after with:-
TextBlock tb = treeViewItem.Descendents()
.OfType<TextBlock>()
.Where(t => t.Name == "myTextBlock")
.FirstOrDefault();
what version of silverlight is this?
And what year of " Aug 10 at 18:55" is this post from?
in the current version of SL4 it does not seem to be there..
can also try this
TextBlock txtBlk = grd.FindName("txtBlkName") as TextBlock;
where grd = your root element (Parent of the element you are looking for)
Related
In my UWP app I want to create a Page object that I can print. Currently all I have is a list of FrameworkElement (WebViewBrush). Is there some way I can make a Page, whose only feature is a FrameworkElement?
I'm thinking something like:
Page newPage = new Page();
newPage.Add(frameworkElement);
That doesn't work, but that's the sort of thing I'm looking for. I can't see anything on https://msdn.microsoft.com/library/windows/apps/br227503 which demonstrates this but I might be looking for the wrong thing... any advice appreciated, thank you.
EDIT
EDIT 2
A Page can only contain a single child. If you only want a single FrameworkElement displayed in the Page then you can do:
newPage.Content = frameworkElement;
Otherwise you will need to create a container that can contain multiple children:
StackPanel panel = new StackPanel();
panel.Children.Add(frameworkElement);
// Add your many other children.
newPage.Content = panel;
There are of course many other types of container that you can use.
Update
Just to summarise the eventual solution. Although it might not be ideal it was settled on generating a second pageList due to the fact that cloning through VisualBrush is not an option in UWP. In theory the brushes should not be large and shouldn't take up too much memory.
I am creating a custom ChildWindow that I want to use with a DataTemplate.
The DataTemplate will apply to the "body" of the window, but then, separate from that, I want to always display two buttons, "Save" and "Cancel".
I have no idea how to accomplish that... Any help would be greatly appreciated!
Grab a copy of your ChildWindowStyle from your SdkStyles.xaml to give you a foundation for building your custom control template on. To keep a DataContext you could throw it in a UserControl as UserControl.Resources or if you're just populating ContentPresenters etc you can put the template in your own resource dictionary or wherever you like (though you might want to specify a unique x:Key name for it.) Just depends on how you'd like to use it.
Make your desired changes to the template and also add your Buttons etc. Then you can either set it as the default by replacing the Default BasedOn value in your resource dictionary to point to it or call that style explicitly.
Personally I prefer Expression Blend for all of this and there's even some tutorials out there to help you along with a Web Search (which I might suggest first next time.) Like what you might find here... Hope this helps! :)
I've just started developing in Silverlight, and I have a calendar control which shows details for each day.
The text within the calendar is held within lots of textblocks, for some browsers the text size might be too big, so I want to have a slider control on the 'usercontrol' which allows the user to adjust the font size.
I'm building the calendar through c# code, so my question is.. what is the best way to 'wire' this up. I'm guessing it would be one of these options.
Add an event to the slider control for ValueChanged, then iterate through all TextBlocks setting the fontsize to the new size. This seems long-winded.
Maybe using a 'Style', which is attached to each TextBlock, then just changing the FontSize of the 'Style'.. ?? maybe ?
Using 'binding' & 'Dependancy Property'. I've looked into this, and it seems to be the way to do it, but I can't find an example where you're passing a value from one control to multiple other ones. Maybe I'm missing something.
I can do option 1 quite easily, but I want to learn about alternative methods of doing this.
Thanks
Rich.
A way to handle this is to not use fixed sizes but to size everything to its content. that way the control will get bigger when a larger font size is selected. Just like the TextBlock.
I've actually got this working now using option 3 which I'm happy with, it was very simple, but there seemed to be little documentation on it (maybe I was searching for the wrong thing).
It was as simple as adding a few lines...
Binding bind = new Binding("Value");
bind.Source = FontSlider;
The for every control that I want to apply the FontSlider's 'Value' to.. I do this...
MyTextBlock.SetBinding(TextBlock.FontSizeProperty,bind);
Simples.
Cheers
Rich.
I'd like to be able to use arbitrary C# expressions in XAML. Usually this would be to compute a property for a UI element based on two bound values.
For example calculating the width of a UI element based on two other properties.
This is a contrived example of what I'd like the XAML to look like:
<TextBox
x:Name="textBox1"
/>
<TextBox
x:Name="textBox2"
/>
<Rectangle
Height={Double.Parse(textBox1.Text) + Double.Parse(textBox2.Text)}
/>
Of course there is no built-in way of doing this in XAML.
I know that I could use a MultiBinding combined with a custom converter and this is usually the way I do this kind of thing. However it seems to me that it would be so much simpler to just include some C# code in the XAML and I was wondering if anyone out there had already solved this problem with a XAML extension or something else.
You embed C# code into XAML like this:
<x:Code>
<![CDATA[
void ButtonOnClick(object sender, RoutedEventArgs args)
{
Button btn = sender as Button;
MessageBox.Show("The button labeled '" +
btn.Content +
"' has been clicked.","Information Message");
}
]]>
</x:Code>
But this approach is not recommended at all because it mixes the pure presentation layer with business logic.
I've seen custom Xaml converters that take IronPython code and Invoke the DLR. It's not quite C#, but its certainly is less ugly than the approach of using [CDATA] tags.
http://pybinding.codeplex.com/
This is the link to an open source project on the matter.
Wrap your expression into a public property and bind to that property.
In C# codebehind:
public double Heigth
{
get { return Double.Parse(textBox1.Text) + Double.Parse(textBox2.Text); }
}
In XAML:
<Rectangle Height={Binding Heigth} />
Please mind that with the code like
Height={Double.Parse(textBox1.Text) + Double.Parse(textBox2.Text)}
it's particularly hard (although not completely impossible, keeping Linq Expressions in mind) to get the value reevaluated as soon as some of the operands change. The automatic update of the target value when the source changes is one of the major advantages of WPF bindings.
I have an answer to my question now. It isn't the answer I was originally looking for, and it is a bit long winded but it does work.
I was reading this post by Josh Smith. He recommends not using value converters but pushing the calculations down into the view-model and exposing it as a property:
http://groups.google.com/group/wpf-disciples/browse_thread/thread/3fe270cd107f184f?pli=1
In my case the text for both 'textBox1' and 'textBox2' should be bound into the view-model, so when they change in the view-model I know its time to do the calculation and update the dependent property. The dependent property then fires its property changed event and the UI updates from that.
If you have a case where you want to make the expression depend on read-only control properties, that you can't easily bind to the view-model, you can follow the advice presented here:
Pushing read-only GUI properties back into ViewModel
I still would like to have the ability to embed (non-business logic) expressions in the XAML. But seeing as this is not built-in any way of doing it is likely to be a bit of a hack. Going through the view-model seems to be the correct way of doing this, but maybe one-day I'll experiment with writing a markup extension that allows expression in XAML.
i wonder if there is a way to access a control's templatepart from within c# for modifying the part (e.g. hiding, etc..). is it possible to get a reference to the part with pure c#?
i don't want to touch the controls template.
thanks
j.
It is possible, but its quite nasty.
On the Template there is a method called FindName, which needs two arguments: the name and the FrameworkElement that has the ControlTemplate as Template. Of course, you need to set the name of the element in the ControlTemplate...
Another more elegent solution is to use a Binding in the ControlTemplate to determine the visibility.. That way you do not need to do stuff in your code behind and you can keep it Xaml only...