I am trying to bind some xml data to a listbox using WPF but i am not able to output anything. the xaml doesn't display any errors and the project builds and runs but no data is displayed in the listbox.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:XMLDataProviderTutorial"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<XmlDataProvider x:Key="Products">
<x:XData>
<ROOT xmlns="">
<ITEM>Socks</ITEM>
<ITEM>Shoes</ITEM>
<ITEM>Toothbrush</ITEM>
</ROOT>
</x:XData>
</XmlDataProvider>
</Window.Resources>
<Grid>
<ListBox
Background="Beige"
ItemsSource="{Binding
Source={StaticResource Products},
XPath='//ITEM'}"/>
</Grid>
</Window>
In the end, added in a listbox item template fixed the issue, for some reason it didn't update in the editor, had to run it to see the output
<ListBox
MinHeight="200"
Background="Honeydew"
ItemsSource="{Binding
Source={StaticResource Products},
XPath='//ITEM'}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding InnerText}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Related
I have the following code to fit the grid exactly to the window.
As you can see in the screenshot, the grid is running out of the window on the bottom and right side. Do you guys have any idea why this is happening? and how to do it properly?
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Topmost="true"
Background="Aqua"
WindowStartupLocation="CenterScreen"
DataContext="{Binding Main, Source={StaticResource Locator}}"
Title="MainWindow" Height="500" Width="500">
<Grid
Width="{Binding ActualWidth, RelativeSource = {RelativeSource AncestorType = {x:Type Window}}}"
Height="{Binding ActualHeight, RelativeSource ={RelativeSource AncestorType = {x:Type Window}}}">
<Border Opacity=".9" BorderBrush="Blue" BorderThickness="2"/>
</Grid>
</Window>
If you bind the actual widths and heights of the window, the Grid will exceed the Window, as the content area is smaller than the window itself. Remove the bindings. The Grid will be sized automatically to occupy the available space if you do not explicitly set a Width and Height.
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Topmost="true"
Background="Aqua"
WindowStartupLocation="CenterScreen"
DataContext="{Binding Main, Source={StaticResource Locator}}"
Title="MainWindow" Height="500" Width="500">
<Grid>
<Border Opacity=".9" BorderBrush="Blue" BorderThickness="2"/>
</Grid>
</Window>
i am trying to bind a Textblock's Text property of MainWindow to a Listbox's Items.Count of another Usercontrol, and the textblock of Mainwindow failed to read the value of binding source.
but if both textblock and listbox belong to the same usercontrol or window, the binding is fine.
i know i can define a property of in the usercontrol and make it exposed to other framework elements(e.g. textblock) of Mainwindow, and then it can be bond.
i just cannot understand why the binding to the listbox of another usercontrol failed. any suggestion will be greatly appreciated.
here below is the sample i made for better explanation.
UserControl Xaml:
<UserControl x:Class="stackoverFlow.UserControl1"
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:stackoverFlow"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel>
<ListBox x:Name="lbDemo">
<ListBoxItem>
<TextBlock Text="element 01"/>
</ListBoxItem>
<ListBoxItem>
<TextBlock Text="element 02"/>
</ListBoxItem>
<ListBoxItem>
<TextBlock Text="element 03"/>
</ListBoxItem>
</ListBox>
<!--binding to the control of the same usercontrol is fine-->
<TextBlock Text="{Binding ElementName=lbDemo,Path=Items.Count,StringFormat='there are {0} items in the listbox.'}"/>
</StackPanel>
</UserControl>
MainWindow Xaml:
<Window x:Class="stackoverFlow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:stackoverFlow"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<StackPanel>
<local:UserControl1 x:Name="userControlDemo"/>
<Separator Margin="0 5 0 15"/>
<!--binding failed-->
<TextBlock Text="{Binding ElementName=userControlDemo,Path=lbDemo.Items.Count, StringFormat='there are {0} items in the listbox of Usercontrol1'}"/>
</StackPanel>
</Window>
In your User control, you should add a get accessor like this:
public int ListCount {
get {
return this.lbDemo.Items.Count;
}
}
And in your Main Window, you call it like this:
<TextBlock Text="{Binding ElementName=userControlDemo, Path=ListCount, StringFormat='there are {0} items in the listbox of Usercontrol1'}" />
XAML:
<WrapPanel>
<TextBox ScrollViewer.VerticalScrollBarVisibility="Auto" AcceptsReturn="True"/>
<TextBox ScrollViewer.VerticalScrollBarVisibility="Auto" AcceptsReturn="True"/>
</WrapPanel>
As you can see at the following picture, the second TextBox is cut after it wrapped, to second line.
Picture:
Put the WrapPanel in a ScrollViewer if you want to be able to scroll its content:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Window1" Height="300" Width="300">
<ScrollViewer>
<WrapPanel>
<TextBox Width="400"></TextBox>
<TextBox Height="500" ScrollViewer.VerticalScrollBarVisibility="Visible"></TextBox>
</WrapPanel>
</ScrollViewer>
</Window>
The WrapPanel won't automatically adopt to the size of the window.
I'm working on a windows phone project.
There is something i don't really understand about my xaml.
Here it is:
<Page
x:Class="CitiBox.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="using:CitiBox.Converters"
xmlns:views="using:CitiBox.Views"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Page.Resources>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Page.Resources>
<Grid>
<!--<TextBlock Text="Test1" Visibility="{Binding Test2, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Text="Test2" Visibility="{Binding Test1, Converter={StaticResource BooleanToVisibilityConverter}}"/>-->
<views:LoadingView Visibility="{Binding Test2, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<views:DrawerView Visibility="{Binding Test1, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</Grid>
</Page>
As you can see there are two textblock that are commented and two views (user controls). You also can see that i binded the visibility of those four elements to two booleans with a BooleanToVisibilityConverter.
What surprises me is that if i test this code with the two textblocks, it works and if i try it with the views it doesn't. my views contains only a textblock with a message, nothing fancy..
Here is what they look like:
<UserControl
x:Class="CitiBox.Views.LoadingView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CitiBox.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
DataContext="{Binding Loading, Source={StaticResource Locator}}">
<Grid>
<TextBlock Text="Loading!!"/>
</Grid>
</UserControl>
Would you have an idea of what it could be ?
Thanks in advance,
Guillaume.
The problem is the use of DataContext. Your MainPage has a DataContext :
DataContext="{Binding Main, Source={StaticResource Locator}}"
LoadingView also has a DataContext
So, when you write this code :
You try to find Test2 as a field in the DataContext of the LoadingView because you're in the same View. To avoid this behavior, you can try this :
<views:LoadingView Visibility="{Binding ElementName=Page,Path=DataContext.Test2, Converter={StaticResource BooleanToVisibilityConverter}}"/>
Or you can write a class called NavigationService inherited from INavigationService (MVVM Light)
Each view in your project will be a Page and you will be a transition (like fade) between all your pages
In your UserControl, you are explicitly setting the DataContext.
DataContext="{Binding Loading, Source={StaticResource Locator}}"
This means that the following binding will not work:
Visibility="{Binding Test2, Converter={StaticResource BooleanToVisibilityConverter}}"
The reason why is because the binding is looking for Test2 in the current DataContext of the UserControl. Instead, you need to be looking for Test2 in the parent control's DataContext.
Try this instead:
Visibility="{Binding DataContext.Test2, RelativeSource={RelativeSource AncestorType=Page}, Converter={StaticResource BooleanToVisibilityConverter}}"
I think your Problem is DataContext Because The Page DataContext is
DataContext="{Binding Main, Source={StaticResource Locator}}"
Where as You set usercontrol dataContext as DataContext="{Binding Loading, Source={StaticResource Locator}}" Try to Change Your Code Like this
<Page x:Class="CitiBox.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:converters="using:CitiBox.Converters"
xmlns:views="using:CitiBox.Views"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
DataContext="{Binding Main, Source={StaticResource Locator}}"
x:Name="Page">
<Page.Resources>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Page.Resources>
<Grid>
<!--<TextBlock Text="Test1" Visibility="{Binding Test2, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Text="Test2" Visibility="{Binding Test1, Converter={StaticResource BooleanToVisibilityConverter}}"/>-->
<views:LoadingView Visibility="{Binding ElementName=Page,Path=DataContext.Test2, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<views:DrawerView Visibility="{Binding ElementName=Page,Path=DataContext.Test1, Converter={StaticResourceBooleanToVisibilityConverter}}"/>
</Grid>
</Page>
I have a DataTemplate with a ListView control. This DataTemplate is located in Templates.xaml (which is a ResourceDictionary). Template.xaml is then included into my main UserControl SourceManager.xaml through ResourceDictionary.MergedDictionaries. I want to raise the SelectionChanged event of the DataTemplate's ListView but I want the handler in the code behind to be in SourceManager.xaml.cs.
How can I achieve that?
Templates.xaml:
<ResourceDictionary x:Class="LawBib.Templates"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DataTemplate x:Key="SectionTemplate">
<StackPanel>
<TextBlock Text="{Binding XPath=#Title}" />
<ListView x:Name="GroupList" ItemsSource="{Binding XPath=Source}">
<ListView.Template>
<ControlTemplate>
<WrapPanel IsItemsHost="True">
</WrapPanel>
</ControlTemplate>
</ListView.Template>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="images/source.png" />
<TextBlock Text="{Binding XPath=#Title}" HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</DataTemplate>
SourceManager.xaml:
<UserControl x:Class="LawBib.SourceManager"
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" Background="#f5f7f8">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources.xaml" />
<ResourceDictionary Source="Templates.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
...
</UserControl>
Since SelectionChanged is a RoutedEvent, you can apply it to your UserControl like so:
<UserControl ...
ListView.SelectionChanged="MyEventHandler" />
Be aware that this event handler will be called for all Selector derived classes (as Selector is where the event is defined and raised) that are descendants of your UserControl, which includes ComboBox, Menu, ListBox, etc.
Create a Behavior
drop it in the Data Template.
that's it.