How to bind two different class properties in DataTemplate - data-binding

I am trying to bind two properties from different classes in DataTemplate.
<DataTemplate x:Key="DemoItemTemplate" x:DataType="local:DemoInfo">
<NavigationViewItem Visibility="{Binding Visibility, Mode=TwoWay}" Content="{x:Bind Name}"/>
</DataTemplate>
DataType set as DemoInfo for this DataTemplate and Name value updated from DemoInfo.
I have tried view model as source and relative source binding. But Visibility property binding not working from ViewModel class. Any suggest how to achieve this?
Visibility="{Binding Visibility, Source={StaticResource viewModel}}"

AFAIK , you cant use multibinding in UWP , you can try to use Locator What is a ViewModelLocator and what are its pros/cons compared to DataTemplates?

How to bind two different class properties in DataTemplate
If you bind Visibility with StaticResource, please declare ViewModel class in your page Resources like the following.
ViewModel
public class ViewModel
{
public ViewModel()
{
Visibility = false;
}
public bool Visibility { get; set; }
}
Xaml
<Page.Resources>
<local:ViewModel x:Key="ViewModel" />
</Page.Resources>
<DataTemplate x:DataType="local:Item">
<TextBlock
Width="100"
Height="44"
Text="{x:Bind Name}"
Visibility="{Binding Visibility, Source={StaticResource ViewModel}}" />
</StackPanel>
</DataTemplate>
Update
If you want Visibility value changed dynamically at run-time, you need implement INotifyPropertyChanged interface for ViewModel class.
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
Visibility = false;
}
private bool _visibility;
public bool Visibility
{
get
{
return _visibility;
}
set
{
_visibility = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string PropertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
}
For more detail please refer Data binding in depth official document.

Related

Is there any way to force a WinUI 3 Datagrid to refresh (re-render) after the bound ItemsSource has changed?

I'm using the CommunityToolkit.WinUI.UI.Controls.DataGrid control.
The ItemsSource property is bound to an ObservableCollection of objects.
These objects have a boolean-type property that I am binding checkboxes to.
The problem:
When a background operation changes the boolean value of some of the objects in the ObservableCollection, the datagrid doesn't reflect the new value (checkbox checked or not checked).
However, if I scroll the datagrid so the affected rows are no longer visible, then scroll back to the affected rows, the value is now rendered correctly.
So there is a work-around -- except for a datagrid that doesn't have enough rows to scroll.
Applicable Code:
<controls:DataGrid Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding UiModel.Dictionary.Values}" CanUserReorderColumns="False" GridLinesVisibility="All" BorderBrush="LightGray" BorderThickness="1" PointerPressed="DataGrid_PointerPressed">
UIModel.Dictionary.Values definition:
IDictionary<string, ObservableCollection<MyClass<T>>>
The IDictionary is assigned an ObservableDictionary as defined at https://learn.microsoft.com/en-us/uwp/api/windows.foundation.collections.iobservablemap-2?view=winrt-22621.
MyClass definition:
using CommunityToolkit.Mvvm.ComponentModel;
public class MyClass<T> : ObservableObject
{
public string Display { get; set; }
public T Identifier { get; set; }
private bool _selected;
public bool Selected
{
get { return _selected; }
set
{
_ = SetProperty(ref _selected, value);
}
}
}
The DataTemplate binding:
<controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Style="{StaticResource CompactCheckbox}" IsChecked="{Binding Path=[0].Selected, Mode=TwoWay}" HorizontalAlignment="Center" MinWidth="0" />
</DataTemplate>
</controls:DataGridTemplateColumn.CellTemplate>
Adding UpdateSourceTrigger=PropertyChanged to the CheckBox binding doesn't help.
Also adding Mode=TwoWay, UpdateSourceTrigger=PropertyChanged to the ItemsSource binding of the DataGrid doesn't help either.
The class in which the Selected property is defined should implement INotifyPropertyChanged and raise the PropertyChanged event in the setter:
private bool _selected;
public bool Selected
{
get { return _selected; }
set { _selected = value; NotifyPropertyChanged(); }
}

Binding two viewModel to one view

i am trying to bind my MasterViewModel where i have initiated two original viewModel to one view. But i am not getting any data so i must be doing the binding wrong. I have found several post
I have tried
in Xaml
<Label
x:Name="SectionRequired"
Grid.Row="2"
HorizontalOptions="End"
IsVisible="{Binding PostViewModel.IsRequired, Source={x:Reference PostViewModel}}"
Text="{x:Static resources:AppResources.AlertRequired}"
TextColor="Red" />
And also followed this solution but i was getting an expcetion that its used lika markup extenstion 'local1:PostViewModel' is used like a markup extension but does not derive from MarkupExtension.
https://stackoverflow.com/questions/50307356/multiple-bindingcontexts-on-same-contentpage-two-different-views
My Master
class MasterPostsViewModel : BaseViewModel
{
public PostViewModel postViewModel { get; set; }
public CategoriesViewModel categoriesViewModel { get; set; }
public MasterPostsViewModel()
{
postViewModel = new PostViewModel();
categoriesViewModel = new CategoriesViewModel();
}
}
}
Conte page
I have set the binding to one field here and that works, buit having to do that for the whole page is not what i want.
MasterPostsViewModel ViewModel;
protected override void OnAppearing()
{
base.OnAppearing();
BindingContext = ViewModel = new MasterPostsViewModel();
NameRequired.IsVisible = ViewModel.postViewModel.IsRequired;
}
Can you help please
instead of
IsVisible="{Binding PostViewModel.IsRequired, Source={x:Reference PostViewModel}}"
just use
IsVisible="{Binding postViewModel.IsRequired}"
your property name is postViewModel is lower case
also, get rid of this line - it will break the binding you have setup in the XAML
NameRequired.IsVisible = ViewModel.postViewModel.IsRequired;

Binding TextBlock text not update except Initial

I'm new on Caliburn.Micro.
The Binding a text on TextBlock.
The text of TextBlock is changed on start up or initialize on ViewModel,
But it would not change in fired function.
I don't know why for a day.
I need any help badly.
Here is code what i wrote.
In View
<TextBlock Grid.Row="0" FontSize="72" Foreground="White"
HorizontalAlignment="Center" VerticalAlignment="Center"
x:Name="DisplayedPhoneNumber"/>
In ViewModel
//! Scren Binding.
public string DisplayedPhoneNumber { get; set; } ="0103214321";
When i press a button on view, i call a function like this,
In View
<Border Style="{StaticResource StyleNumberKeyBorder}">
<Button Content="1" Style="{StaticResource StyleNumberKeyButton}"
cal:Message.Attach="[Event Click]=[Action CmdNumberClick(1)]"/>
</Border>
In ViewModel, CmdNumberClick function like this...
public void CmdNumberClick(string pressed_number)
{
DisplayedPhoneNumber = "plz change...";
}
I check the fired function, and checked DisplayedPhoneNumber is changed,
But TextBlck was not changed.
Please help.
public string DisplayedPhoneNumber { get; set; }
needs to be
private string _displayedPhoneNumber;
public string DisplayedPhoneNumber{
get{ return _displayedPhoneNumber;}
set{
_displayedPhoneNumber = value;
NotifyOfPropertyChanged(() => DisplayedPhoneNumber);
}
}
Associated ViewModel has to inherit PropertyChangedBase or a base class that derives INotifyPropertyChanged;

Xamarin forms Picker Binding error

I have a picker control:
<Picker Title="Number of People"
ItemsSource="{Binding SomeList, Source={x:Static local:MyModelHandler.MyModel}}"
SelectedItem="{Binding SomeListSelectedIndex, Source={x:Static local:MyModelHandler.MyModel}}">
</Picker>
when trying to build i get "No property, bindable property, or event found for 'ItemsSource'" error.
Above that i have a label:
<Label Text ="{Binding SomeLabel, Source={x:Static local:MyModelHandler.MyModel}, Mode=OneWay}"></Label>
And that binding works perfectly
MyModelHandler is an static class that allowes only one Model
public static class MyModelHandler
{
private static MyModel myModel = new MyModel();
public static MyModel MyModel
{
get
{
return myModel;
}
}
}
And Model is simple:
public class MyModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int selectedNumber = 1;
private string someLabel = "";
public IList<int> SomeList
{
get
{
return Enumerable.Range(1, 10).ToList();
}
}
public int SomeListSelectedIndex
{
get
{
return SomeList.IndexOf(this.selectedNumberOfPeople);
}
set
{
this.selectedNumber = SomeList[value];
}
}
public double SomeLabel
{
get
{
return this.someLabel;
}
set
{
this.someLabel= value;
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
...
}
Edit: Using Xamarin 4.3
You might check your Xamarin.Forms version.
The ItemsSource property was introduced in Xamarin.Forms 2.3.4.184-pre1, see release notes here:
https://developer.xamarin.com/releases/xamarin-forms/xamarin-forms-2.3/2.3.4-stable/#2.3.4.184-pre1.
If you are using an older Xamarin.Forms version you will get the Xamarin.Forms XAML error "No property, bindable property, or event found for 'ItemsSource'".
That is a very strange way to set up the binding context for a view. The fact you have to specify the source for each element adds a lot of extra boilerplate code.
Try setting the bindingcontext to the model in the the view constructor
BindingContext = new MyModel ();
Then the XAML becomes
<Picker Title="Number of People"
ItemsSource="{Binding SomeList}"
SelectedItem="{Binding SomeListSelectedIndex}">
</Picker>
Or use a proper MVVM framework and save yourself a lot of grief. I can recommend FreshMvvm.
https://github.com/rid00z/FreshMvvm

WPF - How to bind to a Dependency Property of custom class

I'm once again in WPF binding hell :) I have a public class (Treatment) as follows:
public class Treatment()
{
...
public Ticker SoakTimeActual;
...
}
Within Ticker is a Dependency Property:
public class Ticker : FrameworkElement
{
// Value as string
public static readonly DependencyProperty DisplayIntervalProperty = DependencyProperty.Register("DisplayInterval", typeof(string), typeof(Ticker), null);
public string DisplayInterval
{
get { return (string)GetValue(DisplayIntervalProperty); }
set { SetValue(DisplayIntervalProperty, value); }
}
...
}
In my app, a single Treatment object is created and is meant to be easily accessible in XAML (in app.xaml ):
<Application.Resources>
<ResourceDictionary>
<u:Treatment
x:Key="currentTreatment" />
</ResourceDictionary>
</Application.Resources>
Now, I need to bind to the DisplayInterval dependency property of SoakTimeActual to display this text in its current state. Here is my attempt, which doesn't work:
<TextBlock
Text="{Binding Source={StaticResource currentTreatment}, Path=SoakTimeActual.DisplayInterval}"/>
This, of course, compiles ok, but will not display anything. I'm assuming I've made a mistake with change notification or DataContext or both.
Any insight is appreciated!
WPF binding only operates on properties, not fields.
Therefore, you need change your SoakTimeActual field to a property, like this:
public class Treatment
{
...
public Ticker SoakTimeActual { get; set; }
...
}

Resources