Issue with binding Image.Source in DataTemplate - c#

Consider defining a trivial DataTemplate as follows:
<Page.Resources>
<DataTemplate x:Name="dTemplate" x:Key="DTemplate">
<Image x:Name="image"
Source="{Binding Source=imageSource, FallbackValue=./DesignData/foo.jpg}">
</Image>
</DataTemplate>
</Page.Resources>
Where imageSource is a BitmapImage defined appropriately in the code behind.
Then set up its use somewhere in the page in the normal way
<ListView x:Name="listView" d:DataContext="{d:DesignData Source=./DesignData/SampleData.xaml}"
ItemsSource="{Binding oCollection}"
ItemTemplate="{StaticResource DTemplate}" >
</ListView>
Where oCollection is an observable collection of the correct type.
This all works fine at runtime.
The problem is that the page doesn't render in in Design View in VS.
Neither the ListView (nor the image) display.
The only fix I've found is to remove both of the explicit bindings in the XAML, as follows:
Source="{Binding Source=, FallbackValue=./DesignData/Socrates.jpg}">
...
ItemsSource="{Binding}"
Which is obviously not a good solution, since it now won't run.
I can fix the ItemsSource binding in the code behind, as follows
thisPage.listView.ItemsSource = oCollection;
But I can't figure how to fix the Image source binding within the DataTemplate. From looking around at other related Q&As it seems that trying to set binding for a DataTemplate within the code behind is pretty ugly, and non-recommended.
Any suggestions, on how to fix the XAML or the code behind, greatly appreciated.

Related

(UWP) How do I access my code-behind file from within a DataTemplate?

This is basically a data binding issue.
Simply put, I have a ListView who's items are generated and use a DataTemplate to present those items. Within a DataTemplate, however, the DataContext changes to the x:DataType being used, and so I have no way to access properties located in my code-behind C# file, or even properties contained in my ViewModel. Hopefully I am being clear here:
<ListView
x:Name="MyListView"
ItemsSource="{x:Bind mainViewModel.AdvancedNoteCollection, Mode=OneWay}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="Models:Note">
<Grid>
<TextBlock Text="{ When trying to bind, I am stuck within the DataContext of the Note data type! }" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
However, in reality, my DataTemplate is located in a external ResourceDictionary file, which makes my situation a little more challenging. The external ResourceDictionary DOES have its own code-behind file, though, which allows me to use x:Bind in addition to traditional Binding.

UWP: How do I remove a Binding in code?

How do I remove a Binding in code? In one case I used SetBinding to create a Binding. In another case I created a Binding via XAML. But there don't seem to be a way to completely remove the Binding.
There are a bunch of ways you can go about it.
Let's assume that you have the below XAML
<Page>
...
<Page.DataContext>
<vm:MyPageViewModel x:Name="ViewModel" />
</Page.DataContext>
...
<Grid x:Name="rootLayout">
<ListView x:name="PeopleListView" ItemSource="{Binding myItemsCollection}"/>
<Textbox x:name="SomeTextBox" Text="{Binding myTextProp}"/>
</Grid>
</Page>
Now in C# there are a bunch of ways you can remove the binding of the PeopleListView control. Below are a few.
Set the DataContext of the PeopleListView to null. This would make it not use parent DataContext.
Another way is to set the PeopleListView.ItemSource property to null. This would remove the existing XAML binding and replace it with null.

UserControls not rendering

Okay, to start, I'm pretty inexperienced with WPF and XAML, so any pointers or advice would be greatly appreciated.
I have a scheduling program that I'm working on that I need some help setting up. I had things working previously, but it wasn't organized correctly. I had UI elements in my ViewModels that I would add to a StackPanel at the initialization of the MainWindow. Generally not MVVM style coding. So I made some views (UserControls) to display the things I have, and most everything broke.
Basically, I have a Schedule ViewModel that has some parameters and a list of a different Room ViewModels. Each Room ViewModel has a RoomSchedule ViewModel that contains a list of RoomEvent ViewModels.
I'm trying to write controls for the things that need displaying. I've created a Schedule view, which has a list box of Room views, and the Room view uses the RoomEvent view to display the events of the room. The Room view uses the WPF Extended Toolkit's TimelinePanel, the rest of the controls are pretty much basic controls. The general idea has been: a model provides data to the ViewModel, which massages that data to what needs to be displayed. So an Event should know how to display itself, a Room should know how to display itself, and the Schedule should know how to display itself.
The problem I'm running into is: now that I've scooted everything from the xaml.cs or ViewModel files to their appropriate places, the controls aren't rendering at all. I've been reading other SO postings where people have the same problem, but none of them seem to work for beginner stuff like this. I think I'm close, it seems like all the controls are being created, and the DataContext's are being set correctly, but nothing is showing up.
This is, basically, what I have so far. I left some of the xaml boilerplate stuff off for succinctness:
Schedule.xaml:
<StackPanel>
<ListBox ItemsSource="{Binding Rooms}" >
<ListBox.ItemTemplate>
<DataTemplate>
<localcontrols:RoomView ScheduleStart="{Binding ElementName=ScheduleControl, Path=DataContext.Start}"
</DataTemplate>
<ListBox.ItemTemplate>
</ListBox>
</StackPanel>
RoomView.xaml:
<extended:TimelinePanel BeginDate="{Binding localcontrols:ScheduleStart}" EndDate="{Binding localcontrols:ScheduleEnd}"
<ItemsControl ItemsSource="{Binding Path=mRoomSchedule.mScheduledEvents}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<localcontrols:EventView />
</DataTemplate>
</ItemsControls.ItemTemplate>
</ItemsControl>
</extended:TimelinePanel>
EventView.xaml:
<Border BorderThickness="1" BorderBrush="Black" extended:TimelinePanel.Date="{Binding mStartTime}" extended:TimelinePanel.DateEnd="{Binding mEndTime}">
<TextBlock Background="{Binding mColor}" Text="{Binding mEventID}" />
</Border>
The ScheduleStart and ScheduleEnd are dependency properties defined in RoomView.xaml.cs. My thinking was that Schedule would have Start and End properties that would be set in its constructor, and the RoomViews in the ListBox would bind to those properties to set the TimelinePanel's BeginDate and EndDate.
Maybe your bindings are wrong. When I need to bind to a dependency property I use the ElementName feature of binding to say which control I want and I give the root node a name, in this case Root. It's one way to solve it.
<UserControl
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:Weingartner.Controls"
x:Class="RoomView"
x:Name="Root">
<extended:TimelinePanel
BeginDate="{Binding ElementName=Root, Path=ScheduleStart}"
EndDate="{Binding ElementName=Root, Path=ScheduleEnd}"
>
<ItemsControl ItemsSource="{Binding Path=mRoomSchedule.mScheduledEvents}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<localcontrols:EventView />
</DataTemplate>
</ItemsControls.ItemTemplate>
</ItemsControl>
</extended:TimelinePanel>
</UserControl>

stackpanel with usercontrol and itemsource shows newitemplaceholder

Im about to create a diagram designer, and have create nodes and edges as usercontrols.
I have an stackpanel where I want to place them. I have managed to make it works with the following code:
<Window.Resources>
<DataTemplate DataType="{x:Type Model:Node}">
<Canvas>
<View:NodeUserControl></View:NodeUserControl>
</Canvas>
</DataTemplate>
</Window.Resources>
<StackPanel Name="DisplayArea">
<ItemsControl ItemsSource="{Binding Nodes}" >
</ItemsControl>
</StackPanel>
Where Nodes is an observablecollection
But this also shows an {NewItemPlaceholder} text and I can't figure out why. Would really appreciate if someone could point out my mistake.
EDIT: I have tried to create a new solution with just the beforementioned code and this doenst show the [NewItemPlaceholder}. Now Im really confused can't see the difference and what else that would cause this.
I got the same issue and the cause was that die source data was bound twice: One time to a DataGrid control and a second bound to an ItemsControl. The ItemsControl shows its items on a canvas and also {NewItemPlaceholder} becomes visible there.
The solution was to avoid adding new items to the DataGrid by:
ok. I didn't need adding.

WPF Datatemplating an ItemsControl

I have an ItemsControl whose ItemsSource gets bound to an ObservableCollection<Component> at run time. I have defined a data template for type Component which works fine.
Now Component has a ObservableCollection<Control> and I want to add another ItemsControl inside my Component Datatemplate to render all the controls. Control here is my own custom object not related to a wpf control.
There are different types of controls so I am trying to use an ItemTemplateSelector to select the right template for each type. In the example below to keep it small I have only shown one of the templates "RWString" which I find using a FindResource in MyControlTemplateSelector overriding SelectTemplate. But the SelectTemplate never gets called(using a breakpoint to check). Is there something wrong in my xaml?
<ItemsControl.Resources>
<src:MyControlTemplateSelector x:Key="XSelector" />
<DataTemplate DataType="{x:Type src:Component}" >
<Expander Visibility="{Binding Path=Show}">
<ItemsControl ItemsSource="{Binding Path=Contrls}"
ItemTemplateSelector="{StaticResource XSelector}">
<ItemsControl.Resources>
<DataTemplate x:Key="RWstring" >
<TextBlock Text="{Binding Path=Label}"/>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate><WrapPanel /></ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Expander>
</DataTemplate>
</ItemsControl.Resources>
Update: Contrls is not a typo, its just me using a silly naming system. Contrls is a property of Component of type ObservableCollection<Control>. Also the reason I am trying to use the the ItemsTemplateSelector is that the ObservableCollection<Control> contains objects of generic types like Control<int> Control<string> etc all deriving from Control and apparently you cant create datatemplates referring to generic types.
Update3: Removed update 2 as it was unrelated. I got the ItemTemplateSelector to work by changing StaticResource to DynamicResource. But I don't know why this works...
I'm guessing this doesn't work with a StaticResource as the Resource is inside the ItemsControl which probably has not been created at load time when StaticResources are evaluated.
DynamicResources at load time are evaluated to an expression at load time and then evaluated to the correct value when requested.
Try move the Resource outside of the ItemsControl.
In the line where you bind the nested ItemsControl, is the Path correct? It is currently "Contrls", should it be "Controls"?

Categories