I have a situation where I need to add binding like so:
<DataTemplate x:key="bla">
<views:MyView props:special.MyAttachProperty="{Binding props:special.MyAttachProperty}" />
</DataTemplate>
So the same attache property value will be both,
and change according to changes on the data in the viewmodel.
But this binding fails at run time:
[0:] Binding: 'props:special' property not found on '(my data)', target property: 'views:MyView.MyAttachProperty'
How do I make this work?
Related
In my Xamarin xaml file I have a ProgressBar, where I need to compute Progress (Value/Maximum). So I wrote my Convertor, but I am not able to pass the Maximum to the Convertor.
I tried to use ConverterParameter, but it does not support bindings...
<ProgressBar Progress="{Binding Progress.Value,
Converter={StaticResource Convertor}, ConverterParameter=??}" />
Am I doing something wrong or is there any workaround?
You could pass a reference directly into your converter if it's defined in xaml of whatever class/ViewModel that has all the values you need to calculate progress.
<ProgressBar x:Name="_progressBar" Progress="{Binding Progress.Value,
Converter={StaticResource Convertor}, ConverterParameter={x:Reference _progressBar}}" />
or you could just pass in the value directly in xaml or as a static value defined in a static class from elsewhere in your app, which is of course if you know what the value will be ahead of time.
, ConverterParameter=1}" or
, ConverterParameter={x:Static local:DefaultValues.MaxValue}}"
However, it does sound like you could calculate Progress in your ViewModel on property changed before setting Progress.Value/Progress.MaxValue property, and then you wouldn't even need a converter.
In Prism , MVVM, Windows 8.1 StoreApp I want the ViewModel to capture the SelectItem in a ListView. The ListView contains an ObservableCollection of objects. The ViewModel needs to lookup more details of the selected object and notify the View. The View in turn should show the details of the object.
I have implemented this, but the View allways shows the former object (after selecting a new one)
Of course what I'm looking for is an immediate and correct reaction in the View on selecting an object. Here are my codesnippets, all in VB code.
EDIT: I have put up another - smaller- example, using this approach. I made a recording of the process in this video. Please take a look at it before you read further!!
The objects come from the ViewModel as:
Public Property Persons As New ObservableCollection(Of Person)
They are bound to a usercontrol:
<Grid>
<ListView
ItemsSource="{Binding Persons}"
ItemTemplate="{StaticResource BusinessCard}">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="SelectionChanged">
<Behaviors:ListViewSelectionChangedAction/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</ListView>
</Grid>
Via the Behavior eventually this ends up in the ViewModel through this code:
Sub New(InjectedEventAggregator As IEventAggregator)
LocalEventAggregator = InjectedEventAggregator
LocalEventAggregator.GetEvent(Of PersonIsSelectedEvent)().Subscribe(AddressOf HandlePersonIsSelected, True)
This event is handled by this routine
Public Sub HandlePersonIsSelected(ByVal SelectedPerson As Person)
ActualPerson = SelectedPerson
End Sub
The last part of all this is the property that contains the ActualPerson like so:
Private Property _ActualPerson As Person
Public Property ActualPerson As Person
Get
Return _ActualPerson
End Get
Set(value As Person)
SetProperty(_ActualPerson, value)
End Set
End Property
EDIT: and this is the XAML that should show the selected ActualPerson:
<StackPanel DataContext="{Binding ActualPerson}" >
<Image Source="{Binding Photo}" Stretch="Fill" />
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FirstName}" />
<TextBlock Text="{Binding FamilyName}" />
<TextBlock Text="{Binding Gender}" />
</StackPanel>
</StackPanel>
When I step through the code, I can see that the SelectedItem event is caught in the ViewModel, the handler for the selected person is called, the property is updated. Using Prism this would also mean, that the NotifyPropertyChanged event is fired. It IS fired indeed, otherwise the former object would not show either I guess.
But why is the View not updated immediatelty with the right (Person) object?
If you have a clue.... be my honored guest!
Regards
Let me try to understand what you said in "no reaction on the View". Are you saying the UI is NOT CHANGED, even though the 'ActualPerson = SelectedPerson' is called?
The controls have a binding property called MODE which decides the data flow. The MODE for the TextBlocks that display the Person information can be OneWay. It is possible that the binding is OneTime which is causing the issue.
Can you please confirm what is coming from your Repository? I'm assuming it isn't an observable collection. At least it shouldn't be, I'd think it would be a serialisable POCO object. This means that you will need to add the items to the observable collection. The way I do this if not using a CollectionView is to have a readonly variable of type ObservableCollection, which is never changed. Then when you make the request to messages, I would ensure the collection is cleared, ready for new the new items. Once the messages are returned, loop through each model item (message) within the response and convert them to MessageViewModels (a new class that contains bindable properties and validation (data annotations) as required. As each ViewModel item is created it is added to the observablecollection. The act of adding items to the collection will raise an event the listview is listening for and therefore will display the item (as long as the MessageViewModel has an associated data template.
private readonly _messages = new ObservableCollection<MessageViewModel>();
Public ObservableCollection<MessageViewModel> Messages {get { return _messages;}}
OnNavigateTo
Messages.Clear;
foreach(var message in await _messageRepository,GetMessagesAsync())
{
Messages.Add(new MessageViewModel(){Name = message.Name, Text = message.Text});
}
Does that make sense?
One bad solution, but maybe it is helpful. You can call "again" OnProperyChanged. I say "again" because it is supposed that SetProperty calls it, but I am having some issues with VB.NET and SetProperty too.
Private Property _ActualPerson As Person
Public Property ActualPerson As Person
Get
Return _ActualPerson
End Get
Set(value As Person)
SetProperty(_ActualPerson, value)
OnPropertyChanged("ActualPerson")
End Set
End Property
Edited 04/02/15: the good solution is here: OnPropertyChanged not fired when SetProperty is called
As simple as removing the word "Property" in the private declaration. It is because it is passed ByRef, so it cannot be a property.
When I bind something to the SelectedItem of a ListView using ElementName, the properties cannot be resolved.
I can still build and run my app, but because of this error I'm not sure that I didn't make any typo's.
I read and tried the answer given in ElementName Binding is failing but Source={x:Reference ...} doesn't seem to exist in the WinRT framework.
Just an example:
My page has a property MyContainerObject with an IEnumerable<MyParentObject> inside called MyParents. Each MyParentObject has an IEnumerable<MyChildObject> called MyChildren inside.
The DataContext of my page:
DataContext="{Binding RelativeSource={RelativeSource Self}}"
I have ListView with the following XAML properties:
x:Name = "FirstListView"
ItemsSource = {Binding MyContainerObject.MyParents}
Then I have another ListView with the following XAML properties:
x:Name = "SecondListView"
ItemsSource = "{Binding SelectedItem.MyChildren, ElementName=FirstListView}"
Now ReSharper gives me the following warning:
Cannot resolve property 'MyChildren' in data context of type 'object'.
Add this to your listview:
d:DataContext="{d:DesignInstance model:MyParentObject}"
My XAML has been working fine, referencing a Static Property of a static class
<TextBox IsReadOnly="{x:Static loc:StateMachine.IsReadOnly}" />
I now want to refactor the above, so I can use a ResourceDictionary
So, my resource dictionary is
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:stat="clr-namespace:MyProjectHelper"
>
<stat:StateMachine x:Key="StaticResources" />
</ResourceDictionary>
On my XAML, I removed the namespace reference called loc (which I was using) and I add a reference to the resource dictionary (which works since my views show and converters do their job) but when I add the following code
<TextBox IsReadOnly="{StaticResource StaticResources.IsReadOnly}" />
I get a runtime exception
'Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' Line number '50' and line position '97'.
My research shows this is something wrong wit the XML - it could be a typo (checked) or an unexpected value but I can't see what I need to do to fix this despite looking over SO and Google
I also tried
<TextBox IsReadOnly="{Binding Source={StaticResource StaticResources}, Path=IsReadOnly}" />
but the exception is
'The invocation of the constructor on type 'SeoHelper.StateMachine' that matches the specified binding constraints threw an exception.' Line number '9' and line position '6'.
{StaticResource } binding needs to be able to instantiate your class, and it had problem to do so because the class was static. Your last trial would've worked if only the class wasn't declared as static.
Possible workaround if you need to keep your class static is, you can register the property instead of the class to resource dictionary using StaticExtension :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:stat="clr-namespace:MyProjectHelper"
>
<x:StaticExtension Member="stat:StateMachine.IsReadOnly" x:Key="StaticResources"/>
</ResourceDictionary>
Then binding to the resource can be done as usual :
<TextBox IsReadOnly="{StaticResource StaticResources}" />
I Have a ListBox and I am defining its ItemsTemplate using a custom control. I want the control to be displayed in different ways depending on the state of cetain properties of the object. How can I access the item that the ListBox.ItemTemplate is bound to?
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<custom:MyControl />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
With in the code of the custom control how would I do something like:
if((this.DataContext as SomeObject).CollectionProperty.Count() > 0)
DoAction();
I was accessing dataContext in the constructor and it was null. I accessed it in the this.Loaded event and it worked fine.