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.
Related
I got the following setup for my page:
<ListView ItemsSource="{Binding RecentResults}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Background="Transparent" Orientation="Horizontal" ItemWidth="400" ItemHeight="300" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<ui:CarResultControl Result="{Binding}" Padding="0" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I bind to a local property which provides my results asynchronously. This works perfectly fine.
Now my CarResultControl binds to it's local Result property (which is an DependencyProperty). When I specify Result={Binding} then the property get's updated but not as expected with the CarResult but CarResultControl. If I use Result={Binding Path=.} or similiar, it just doesn't update at all.
As far as I'm used to it in WPF {Binding} actually bound to the data object itself, not the control you´re attaching the binding to. Interesting is that IntelliSense actually shows the properties of the expected CarResult object when I have to choose a binding path for Result.
Is UWP doing it's own thing here again, am I just a fool and doing it wrong or is this really a bug? I struggled for long enough and can't find any info about it.
This actually should be working the way you expect unless you are changing the DataContext of the CarResultControl.
UserControls actually work in a bit weird way - when you set this.DataContext = this in the constructor, then the binding on properties will actually be relative to the UserControl itself.
To fix this you must make sure not to change the DataContext of the control itself. The easiest way is to add x:Name to the root Grid (or whatever control you have in the content of the UserControl and then set its DataContext:
RootGrid.DataContext = this;
This way you will the data context of the RootGrid will be set to the control itself, but the user control's properties will be bound to the data context relative to where the user control is, here to the list item.
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.
Here is Calibrun.Micro example with UWP.
in Bubbling sample, in this file,
there is this line
<Grid cm:Bind.Model="{Binding}">
What is mean ? Why does it necessary ?
I thought Next line is enough for send $dataContext
<Button x:Name="Message" cm:Message.Attach="SelectPhrase($dataContext)" Margin="0,12" />
Please advice me....
Let's analyze the code as quite some things are a bit obscure in Caliburn.Micro as it works through convention:
<Page
x:Class="Features.CrossPlatform.Views.BubblingView"
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:cm="using:Caliburn.Micro"
mc:Ignorable="d">
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock Text="actions" Style="{StaticResource SubheaderTextBlockStyle}" Margin="40,10,40,0"/>
<StackPanel Margin="40,20">
<ItemsControl x:Name="Phrases">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid cm:Bind.Model="{Binding}">
<Button x:Name="Message" cm:Message.Attach="SelectPhrase($dataContext)" Margin="0,12" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</StackPanel>
</Page>
First of all, the page's datacontext (viewmodel) is set through naming convetion. This viewmodel can be found here. As you can see, this viewmodel has a Phrases property and a SelectPhrase(MessageActivityViewModel phrase) method.
If we go down the tree, we have an <ItemsControl x:Name="Phrases"> which binds to the Phrases property, which is a collection of MessageActivityViewModel.
An ItemsControl needs a way to present the items, which is defined in the DataTemplate. This template has a Grid as root object. If the Grid would not use {Binding}, it would inherit the datacontext from the template, which is the current element being rendered (a single MessageActivityViewModel). However, we want to call the SelectPhrase method on the BubblingViewModel and not on the MessageActivityViewModel. To be able to do that, we use {Binding} to tell the Grid binds to the page's viewmodel instead of to the single rendered MessageActivityViewModel.
What the Button does, is sending the datacontext object (being the rendered MessageActivityViewModel item) back to your viewmodel.
$dataContext:
Passes the DataContext of the element that the ActionMessage is attached to. This is very useful in Master/Detail scenarios where the ActionMessage may bubble to a parent VM but needs to carry with it the child instance to be acted upon.
Source: http://caliburnmicro.com/documentation/cheat-sheet
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.
I'm using a static array of objects defined in XAML as my ItemsSource on a list box.
I use:
ItemsSource="{Binding Source={StaticResource theSource}}".
This works great at design time. However, I need to override this at run time so the list box will take it's items from a collection property on my view model. I exposed a Property Named "theSource" and set the Window DataContext in code behind. However, the list is still bound to the static resource... not to the property on my view model.
Any suggestion on the right way to have Design Time data for visualizing the UI and replace with live data at run time?
Just name your Listbox control
<ListBox x:Name="myListBox"
ItemsSource="{Binding Source={StaticResource theSource}}" />
and change it at runtime
myListBox.ItemsSource = datasource;
Second take at this problem:
What's the difference between StaticResource and DynamicResource in WPF?
If you're using WPF, then you might use a DynamicResource instead, and change the definition of this at runtime
It will fail with Silverlight, though, because this lighter framework doesn't support dynamic resources.
Third take
Since you want to use a binding to your controller object, then :
<Page xmlns="http://..." xmlns:your="...">
<Page.DataContext>
<your:DesignTimeObject> <!-- Must be of the same type as in runtime, or at least expose properties and subproperties with the same name -->
<your:DesignTimeObject.List>
<your:Element id="1" />
<your:Element id="2" />
<!-- snip -->
<your:DesignTimeObject.List>
</your:DesignTimeObject>
</Page.DataContext>
<ListBox x:Name="myListBox" ItemsSource="{Binding List}" /> <!-- Binds to the Element list with id="1" , id="2" ... -->
</Page>
With this way, you don't have to change your binding at runtime, set the DataContext once and be done with it.