Content of ContentControl in Resource - silverlight

I have a ContentControl in a RadTileView. If I put in some hard coded text into the content property it works fine. (code below)
<ContentControl Grid.Row="2" Grid.Column="0" Content="Hello World"></ContentControl>
That works...if I put the content into the UserControl.Resources section my application freezes up and displays nothing.
<ContentControl Grid.Row="2" Grid.Column="0" Content="{StaticResource TabControlContent}"></ContentControl>
<UserControl.Resources>
<TextBlock x:Key="TabControlContent" Text="hello world"></TextBlock>
</UserControl.Resources>
Ultimately I would like to have the context be a RadTabControl..but for now Id settle on just having that textblock render.

To get a string into your ContentControl you would, add
xmlns:sys="clr-namespace:System;assembly=mscorlib"
to your usings. Then add this
<UserControl.Resources>
<sys:String x:Key="SingleString">Hello World</sys:String>
</UserControl.Resources>
Which would allow
<ContentControl Content="{Binding Source={StaticResource SingleString}}"/>
Hope this helps.

Related

Bizarre bug when pasting to DataGridTemplateColumn

I have a DataGridTemplateColumn than contains a UserControl:
<DataGridTemplateColumn Header="Projection"
SortMemberPath="SelectedItem"
ClipboardContentBinding="{Binding ProjectionMethod.Value, Mode=TwoWay}"
>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<local:DataGridComboBoxCellControl DataContext="{Binding}"
SelectedItem="{Binding ProjectionMethod.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding ProjectionMethodsTextWrapper, Mode=OneWay}"
ErrorMessage="{Binding ProjectionMethod.ErrorMessage, Mode=OneWay}">
</local:DataGridComboBoxCellControl>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
The UserControl bindings are done with DependencyProperties I set up inside the UserControl definition.
For the most part, the control works fine. But when pasting, even though the contents visually appear to be pasted, the cell never commits the paste contents to ProjectionMethod.Value (even though it is set as the ClipboardContentBinding). Debugging reveals that the setter of ProjectionMethod.Value is never even called.
Even more strangely, the constructor of the UserControl is being called during paste. I have no idea why this is occurring. I am pasting to existing cells, no new rows are being created. I was assuming the ClipboardContentBinding routes straight to the underlying property ProjectionMethod.Value. Why the paste command is even bothering with UI controls is a mystery to me.
It seems this problem might require someone with a fairly deep understanding of WPF.
(Here is the current xaml of the UserControl. Right now it's basically a TextBlock and a ComboBox with a few other controls for displaying errors. Any lines with ElementName=parentControl are bindings to dependency properties. Both the TextBlock and ComboBox bind to the same SelectedItem DP.
<UserControl x:Class="DataGridComboBoxCellControl"
x:Name="parentControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyProject"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<local:MyStringToThicknessConverter x:Key="PopToOne" PopString="1" EmptyString="0"/>
<local:MyStringToVisibilityConverter x:Key="PopToVis" PopString="Visible" EmptyString="Collapsed"/>
</UserControl.Resources>
<Grid ToolTip="{Binding ElementName=parentControl, Path=ErrorMessage, Mode=OneWay}"
IsEnabled="{Binding IsProjectionEnabled}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Grid.ColumnSpan="3" BorderThickness="{Binding ElementName=parentControl, Path=ErrorMessage, Mode=OneWay, Converter={StaticResource PopToOne}}"
BorderBrush="Red"/>
<Control Grid.Column="0"
Margin="1,0"
Template="{DynamicResource local:MyStyleRef, ResourceKey=errorGrid}"
Visibility="{Binding ElementName=parentControl, Path=ErrorMessage, Mode=OneWay, Converter={StaticResource PopToVis}}"/>
<TextBlock Grid.Column="1" Text="{Binding ElementName=parentControl, Path=SelectedItem, Mode=OneWay}" VerticalAlignment="Center"/>
<ComboBox Grid.Column="2"
Style="{DynamicResource local:MyStyleRef, ResourceKey=noText_ComboBoxStyle}"
ItemsSource="{Binding ElementName=parentControl, Path=ItemsSource, Mode=OneWay}"
SelectedItem="{Binding ElementName=parentControl, Path=SelectedItem}" />
</Grid>
</UserControl>
Update
I have now tried getting rid of the UserControl altogether and dumping its xaml code directly into the DataTemplate of the TemplateColumn - the same issue more or less. Visually the paste appears to execute, but the setter of ProjectionMethod.Value is never called and the viewmodel is therefore never updated. I am using the OnPastingCellClipboardContent command to paste.
I think I figured it out. I set the update trigger for the clipboard paste to PropertyChanged:
ClipboardContentBinding="{Binding ProjectionMethod.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
And now the value is being committed immediately when pasting. I don't know what the default behavior is supposed to be, but before the paste values were never committed, even after row leave. And still not sure why the UserControl's constructor was being called.

WPF UserControl or ControlTemplate... (not sure)

I have a listbox where I have to add about 20 static custom items. All the items are based on the same template (something like that) :
<Border>
<StackPanel Orientation="Horizontal">
<Image Source="" Height="30" />
<TextBlock Text="" VerticalAlignment="Center" />
</StackPanel>
</Border>
I don't want to repeat that 20 times in the ListBox.Items I would like to have some kind of UserControl where I could do something Like the following where I could set some custom properties :
<ListBox>
<ListBox.Items>
<MyListBoxTemplate x:Name="Item1" ItemText="Item #1" ItemImageSource="/Image1.jpg" />
<MyListBoxTemplate x:Name="Item2" ItemText="Item #2" ItemImageSource="/Image2.jpg" />
...
</ListBox.Items>
</ListBox>
But I don't wan't to create a userControl just for that!!! Is there an easy way to put that template in the Window.Resources?
Thanks
If you are ONLY using it for that SPECIFIC listbox, you can just assign the ItemTemplate property. This will need to work in conjunction with a collection of custom objects defined in your resources somewhere else. This will save you from creating a custom UserControl, but you will need an object that can be defined in XAML and a list of them in XAML anyway. To be honest, creating a UserControl is relatively painless and may be easier, but it is possible without doing so.
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate TargetType="CustomObjectType">
<Border>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ImageSource}" Height="30" />
<TextBlock Text="{Binding TextContent}" VerticalAlignment="Center" />
</StackPanel>
</Border>
<DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
EDIT: If you are going to use it in more than one place, put the DataTemplate in your Application resources and ive it a key, then assign the ItemTemplate property to {StaticResource MyListBoxItemsTemplateKey}
Not my favorite approach since it uses the XmlDataProvider and XPath syntax (which I tend to always forget). But you can embed your static data as xml within your Window.Resources like so:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<XmlDataProvider x:Key="MyStaticData" XPath="StaticItems" >
<x:XData>
<StaticItems xmlns="">
<StaticItem>
<ItemText>Item #1</ItemText>
<ItemImageSource>/Image1.jpg</ItemImageSource>
</StaticItem>
<StaticItem>
<ItemText>Item #2</ItemText>
<ItemImageSource>/Image2.jpg</ItemImageSource>
</StaticItem>
</StaticItems>
</x:XData>
</XmlDataProvider>
</Window.Resources>
<Grid>
<ListBox>
<ListBox.ItemsSource>
<Binding Source="{StaticResource MyStaticData}" XPath="StaticItem" />
</ListBox.ItemsSource>
<ListBox.ItemTemplate>
<DataTemplate>
<Border>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding XPath=ItemImageSource}" Height="30" />
<TextBlock Text="{Binding XPath=ItemText}" VerticalAlignment="Center" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
Then within your ListBox bind to the XmlDataProvider you specified and use the XPath notation within the bindings to drill down to the data you want the controls to bind to.
This site has a couple good examples too:
http://vbcity.com/blogs/xtab/archive/2010/12/24/more-xpath-examples-in-a-wpf-application.aspx
Hope this helps!

WPF Element Binding in a within a Resource control doesnt work

I have some xaml that will just copy text from one text box to another:
<StackPanel Orientation="Horizontal">
<TextBox Width="100" Height="30" Text="{Binding ElementName=src1, Path=Text}" />
<TextBox x:Name="src1" Width="100" Height="30" />
</StackPanel>
Nothing special, works fine. A bit dumb but just an example.
However if I put the StackPanel as a resource in the Window and create dynamically from code, like this:
<Window.Resources>
<StackPanel x:Key="MySP" Orientation="Horizontal">
<TextBox Width="100" Height="30" Text="{Binding ElementName=src, Path=Text}"/>
<TextBox x:Name="src" Width="100" Height="30" />
</StackPanel>
</Window.Resources>
.. then the element binding doesnt work anymore.
Why? and how to make it work? Any ideas gratefully received.
The following Xaml should work just fine
<Window ...>
<Window.Resources>
<StackPanel x:Key="MySP" Orientation="Horizontal">
<TextBox Width="100" Height="30" Text="{Binding ElementName=src, Path=Text}"/>
<TextBox x:Name="src" Width="100" Height="30" />
</StackPanel>
</Window.Resources>
<StaticResource ResourceKey="MySP"/>
</Window>
You could also use it from code
StackPanel mySP = TryFindResource("MySP") as StackPanel;
if (mySP != null)
{
this.Content = mySP;
}
However, what is the reason for you to have a StackPanel in the Windows Resoures?
If you want to be able to reuse it several times you would have to set x:Shared="False" on the Resource but then you'll get an exception saying something like Cannot register duplicate Name 'src' in this scope the second time you add it.
As far as I'm concerned you should not put that in <Window.Resources>. Only styles, static, dynamic resources and such...
http://msdn.microsoft.com/en-us/library/ms750613.aspx
<Window>
<Window.Resources>
</Window.Resources>
<StackPanel x:Key="MySP" Orientation="Horizontal">
<TextBox Width="100" Height="30" Text="{Binding ElementName=src, Path=Text}"/>
<TextBox x:Name="src" Width="100" Height="30" />
</StackPanel>
<Window>
Having a similar issue, trying to get relative binding to my source control - In my case, I'm creating a designer and need the element as a static so styles can use it's dimensions for centering calculations on a canvas.
Taking a line from [WPF Xaml Namescopes],
ResourceDictionary does not use XAML names or namescopes ; it uses keys instead, because it is a dictionary implementation.
So, directly using ElementName in a resource Dictionary simply does not work, because no name will bind without a NameScope. Also attempted reproducing your situation with Style setters, but no luck - one cannot set an object's name via a Style.
Now, the convoluted solution I cam up with is to
Create a DependencyProperty in the code-behind of the class
you're declaring this resource in.
replace ElementName=Root with RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type namespace:RootClass}} and bind
to said container directly, allowing you to bind to said
DependencyProperty whilst bypassing the names.
If you need bindings to operate between two elements in the same
StaticResource, bind the source to said DependencyProperty as
OneWayToSource or TwoWay, and the destination as OneWay or TwoWay.
1

WPF UserControl Binding Problem

I have the following user control that is embedded within another user control.
<UserControl.Resources>
<DataTemplate x:Key="ContextsTemplate">
<Label Margin="10,0,20,0" Content="{Binding Name}"/>
</DataTemplate>
</UserControl.Resources>
<ItemsControl Name="Contexts"
Background="Transparent"
ItemsSource="{Binding}"
Margin="0,0,0,0"
VerticalAlignment="Center"
AlternationCount="2"
ItemTemplate="{StaticResource ContextsTemplate}">
</ItemsControl>
Here is XAML code for the user control (controlB) above that is embedded in another user control (controlA).
<local:ContextContentsUserControl Height="30" Content="{Binding Contexts}"/>
controlA is displayed on the screen as "(Collection)" but for some reason doesn't show each item in the collections text in the label. Please help.
The problem is here:
Content="{Binding Contexts}"
You meant:
DataContext="{Binding Contexts}"
The reason you got "(Collection)" instead of the content you had defined for controlA is the content you defined in the XAML for ControlA was replaced with your collection. The body of a UserControl's XAML file simply sets its Content property: You replaced it after it was set.
When you declare your ContextContentsUserControl, you are setting its Content property. You need to be setting the DataContext instead:
<local:ContextContentsUserControl Height="30" DataContext="{Binding Contexts}" />

Binding to a data template control property

Is it possible to bind something to a property of a control in a data template entirely in XAML? The following code is a simplified version of the problem I'm running into. I'd like the text of the TextBlock (displayName) to be updated as the user types in the TextBox located in the DataTemplate.
<Window x:Class="WpfApplication4.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfApplication4="clr-namespace:WpfApplication4"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<DataTemplate DataType="{x:Type WpfApplication4:Foo}">
<TextBox Text="{Binding Path=Name}" />
</DataTemplate>
<WpfApplication4:Foo x:Key="testObject" Name="This is a test" />
</Window.Resources>
<StackPanel>
<TextBlock x:Name="displayName" Margin="5" />
<ContentControl x:Name="contentControl" Margin="5" Content="{StaticResource testObject}" />
</StackPanel>
No, at least, not from XAML. You could write code to traverse the visual tree and find the element you want to bind to, but that would be nasty.
But in your particular example, would it not make sense to just bind the TextBlock to the same data object (Foo instance)?

Resources