I'm relatively new to wpf and I quite don't understand binding yet.
I want to have several combo boxes in my application with the same items. The basic solution would be to copy paste but that just isn't good practice. So I thought to put a static resource with the content I want and bind all combo boxes to it. It compiles and runs well but the combo box is empty.
Here's the code:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ItemsControl x:Key="Validations">
<ItemsControl.Items>
<ComboBoxItem>String</ComboBoxItem>
<ComboBoxItem>Numeric</ComboBoxItem>
</ItemsControl.Items>
</ItemsControl>
and here's the combo box:
<ComboBox ItemsSource="{Binding Source={StaticResource Validations}}"/>
I know the solution for this is probably simple but I haven't figured it out yet. I'll keep trying ;)
Thanks
Make the resource a list of strings, not a visual element, then use the StaticResource extension to assign it to the ItemsSource property, like so:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<x:ArrayExtension x:Key="Data" Type="{x:Type sys:String}">
<sys:String>String1</sys:String>
<sys:String>String2</sys:String>
<sys:String>String3</sys:String>
</x:ArrayExtension>
</Window.Resources>
<Grid>
<StackPanel>
<ComboBox ItemsSource="{StaticResource Data}"/>
<ComboBox ItemsSource="{StaticResource Data}"/>
<ComboBox ItemsSource="{StaticResource Data}"/>
</StackPanel>
</Grid>
</Window>
Note the definition of the xmlns:sys namespace (maps to namespace System in assembly mscorlib) and the use of the x:ArrayExtension element to declare a simply array in XAML.
Related
The XAML below is incorrect, but it represents what I'm trying to do. I'm fairly new to WPF, but I want to know if something like this doable without instead declaring the instance in the code behind?
<ListBox Name="lbInstalledFonts" VerticalContentAlignment="Center" DisplayMemberPath="Name" ItemsSource="{Binding Source={new System.Drawing.Text.InstalledFontCollection().Familes}}" />
To elaborate, I only need the list of System.Drawing.Text.InstalledFontCollection().Familes for this ListBox. That's it. So I was thinking I could do it entirely through the XAML in a similar way to how you could bind to a DataSource in ASP.NET (through the use of <% and %> in the aspx/ascx files)? Is this at all possible? I did some searching but didn't have much luck.
Yes, it is possible:
<Window x:Class="HelpStackOverflow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:drawing="clr-namespace:System.Drawing.Text;assembly=System.Drawing"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<drawing:InstalledFontCollection x:Key="InstalledFontCollection" />
</Window.Resources>
<Grid>
<ListBox Name="lbInstalledFonts"
VerticalContentAlignment="Center"
DisplayMemberPath="Name"
ItemsSource="{Binding Source={StaticResource InstalledFontCollection}, Path=Families}" />
</Grid>
</Window>
After thoroughly reading the documentation on flowdocuments (in WPF) it seems as though flowdocument does not easily support databinding. PLEASE say this is not true! I have a listbox using the sample data in Expression Blend and I inserted a textblock into the flowdocument. The textblock (text property) is databinded to the string data in the listbox. After running the project I would expect that the textblock text changes as the listbox selection changes, but nothing happens. Databinding is not working. What is the easiest way to make databinding work with flowdocument?
Here is the XAML.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication1.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>
<DataTemplate x:Key="ItemTemplate">
<StackPanel>
<TextBlock Text="{Binding Property1}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource SampleDataSource}}">
<FlowDocumentScrollViewer Margin="120,64,256,126">
<FlowDocument>
<Paragraph><Run Text="Only A Test"/><InlineUIContainer>
<TextBlock TextWrapping="Wrap" Text="{Binding Collection[0].Property1}" Height="56" Width="112"/>
</InlineUIContainer></Paragraph>
</FlowDocument>
</FlowDocumentScrollViewer>
<ListBox ItemTemplate="{DynamicResource ItemTemplate}" ItemsSource="{Binding Collection}" Margin="0,83.847,52,62.153" HorizontalAlignment="Right" Width="200"/>
</Grid>
</Window>
According to this Microsoft documentation in April 2009, this is not possible:
While there are many great features in flow documents, if your documents are generated from dynamic data, you have a bit of a problem: there is no support for data binding in flow documents. The flow document elements (Section, Table, Run, Paragraph and the like) are dependency objects, but don't define any dependency properties that would allow you to dynamically change or generate content.
I'm trying to build a small MVVM test application, but can't really figure how to display my user control in the MainWindow.
My Solution Explorer:
I got a resource dictionary:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MVVM.ViewModel"
xmlns:vw="clr-namespace:MVVM.View">
<DataTemplate DataType="{x:Type vm:ViewModel}">
<vw:View />
</DataTemplate>
</ResourceDictionary>
I got my view:
<UserControl x:Class="MVVM.View.View"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<DataTemplate x:Key="PersonTemplate">
<StackPanel>
<TextBlock Text="{Binding FirstName}" />
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<ListBox ItemsSource="{Binding Path=Persons}"
ItemTemplate="{StaticResource PersonTemplate}" />
</UserControl>
and My MainWindow
<Window x:Class="MVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:MVVM.ViewModel"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary Source="MainWindowResources.xaml" />
</Window.Resources>
<Grid>
</Grid>
</Window>
The most obvious and easiest way is to add the ContentControl element:
<Grid>
<ContentControl x:Name="mainContentControl" />
</Grid>
And after that set the Content property of this control to your view model, and the corresponding view will be loaded and applied automatically:
this.mainContentControl.Content = new ViewModel.ViewModel();
But I would prefer to use another way without datatemplates:
<Grid>
<vw:View x:Name="mainView"/>
</Grid>
this.mainView.DataContext = new ViewModel.ViewModel();
Build your VS2010 solution, then, go to your MainWindow's XAML.
On the left, there is a toolbar with button "Toolbox"
Open it, it contains all the possible WPF controls you could add to your UI
Your UserControl should appear on top of the list (in a category probably named "MVVM Controls"), just drag&drop it to your UI :)
Sorry for this, I've just started programming with wpf. I can't seem to figure out why the following xaml displays "System.Xml.XmlElement" instead of the actual xml node content. This is displayed 5 times in the listbox whenever I run it. Not sure where I'm going wrong...
<Window x:Class="TestBinding.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<XmlDataProvider x:Key="myXmlSource" XPath="/root">
<x:XData>
<root xmlns="">
<name>Steve</name>
<name>Arthur</name>
<name>Sidney</name>
<name>Billy</name>
<name>Steven</name>
</root>
</x:XData>
</XmlDataProvider>
<DataTemplate x:Key="shmooga">
<TextBlock Text="{Binding}"/>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemTemplate="{StaticResource shmooga}"
ItemsSource="{Binding Source={StaticResource myXmlSource}, XPath=name}">
</ListBox>
</Grid>
</Window>
Any help would be very much appreciated. Thanks!
Your ItemsSource Binding is returning the collection of 'name' elements. These are of type XmlElement. This is done because it allows bindings to get at other properties of the XmlElement, but means that if you textually display the result of the binding then you get System.Xml.XmlElement rather than the textual content.
To get the textual content, add an additional XPath to your ItemTemplate binding to specify that the TextBlock.Text property should bind specifically to the text of the element, not the element object itself:
<DataTemplate x:Key="shmooga">
<TextBlock Text="{Binding XPath=text()}"/> <!-- Note XPath on Binding -->
</DataTemplate>
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)?