'How to make property change reflect in UI with C# WPF XAML
In my WPF application I would like to display a list of buttons when a list of documents are generated in the application based on user action. In my main xaml file: MainDocumentScanView.xaml I have:
<ItemsControl Grid.Row="1"
ItemsSource="{Binding DocDataItemsViewModel.DocDataButtons, Mode=OneWay}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:DocDataButtonControl HorizontalAlignment="Left" VerticalAlignment="Top"
HeaderText="{Binding DocData.Nume}"
ExecuteCommand="{Binding StartScanDocumentCommand}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
ScanningViewModel.cs
namespace mynamespace.ViewModels
{
class ScanningViewModel : BindableBase
{
public DocDataItemsViewModel DocumentDataItems { get; private set; }
public ScanningViewModel()
{
DocumentDataItems = new DocDataItemsViewModel();
}
private void OnDocDataCallback(List<DocData> items)
{
DocumentDataItems.SetDocData(items);
}
}
}
DocDataItemsViewModel.cs
using mynamespace.Models;
using Prism.Mvvm;
using System.Collections.Generic;
using System.Linq;
namespace mynamespace.ViewModels
{
class DocDataItemsViewModel : BindableBase
{
#region Members
private const string LogFileName = "DocDataItemsViewModel";
private List<DocData> _docDataItems;
private List<DocDataButtonViewModel> _docDataButtons;
#endregion Members
#region Properties
public List<DocDataButtonViewModel> DocDataButtons
{
get { return _docDataButtons; }
private set
{
_docDataButtons = value;
RaisePropertyChanged("DocDataButtons");
}
}
#endregion Properties
#region Constructor
public DocDataItemsViewModel(List<DocData> docDataItems) : this()
{
SetDocData(docDataItems);
}
public DocDataItemsViewModel()
{
_docDataItems = new List<DocData>();
}
#endregion Constructor
#region Methods
public void SetDocData(List<DocData> data)
{
LoggerManager.Instance.Info(LogFileName, "Setting new scanned data.");
_docDataItems = data;
DocDataButtons = data
.OrderBy(d => d.Name)
.Select(d => new DocDataButtonViewModel(d))
.ToList();
}
#endregion Methods
}
}
DocDatButtonViewModel.cs
using mynamespace.Models;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace mynamespace.ViewModels
{
class DocDataButtonViewModel : BindableBase
{
#region Members
private const string LogFileName = "DocDataButtonViewModel";
private Boolean _isSelected;
#endregion Members
#region Properties
public DocData DocData { get; private set; }
public Boolean IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected != value)
{
_isSelected = value;
RaisePropertyChanged("IsSelected");
}
}
}
#endregion Properties
#region Constructor
public DocDataButtonViewModel(DocData docData)
{
DocData = docData;
}
#endregion Constructor
}
}
DocDataButtonControl.xaml
<UserControl x:Class="mynamespace.Controls.DocDataButtonControl"
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:mynamespace.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Style TargetType="Border" x:Key="HoverBorderStyle">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="Border.IsMouseOver" Value="True">
<Setter Property="Border.BorderBrush" Value="White" />
<Setter Property="Border.Background" Value="{Binding HoverBrushColor, ElementName=uc}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="StackPanel" x:Key="NoImageStackPanelStyle">
<Setter Property="Margin" Value="10,50"/>
<Style.Triggers>
<DataTrigger Binding="{Binding NoImage, ElementName=uc}" Value="true">
<Setter Property="Margin" Value="10"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Border BorderThickness="0" VerticalAlignment="Top"
HorizontalAlignment="Stretch"
Style="{StaticResource HoverBorderStyle}">
<StackPanel IsHitTestVisible="False" Style="{StaticResource NoImageStackPanelStyle}">
<TextBlock Text="{Binding HeaderText, ElementName=uc}"
HorizontalAlignment="Center"
FontSize="15" Foreground="{Binding GeneralColor, ElementName=uc}"/>
</StackPanel>
</Border>
</UserControl>
DocData.cs
using System;
namespace mynamespace.Models
{
class DocData
{
public String Name { get; set; }
}
}
SetDocData() is called from a different viewmodel with a list of DocData. There is no complilation or runtime error. I tried changing the DataTemplate in MainDocumentScanView.xaml to display a static TextBlock to check that the problem is not with my DocDataButtonControl, but the TextBlock was not displayed either.
What am I missing here to make the data change update the UI properly?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
