I am stumped. I have a user control that contains an ObservableCollection in it. That OC holds instances of a read status class. The read status class has 3 properties, a string, a Progress Bar and a string. The user control should show a list of files to be loaded. Each line having the filename, a progress indicator and a status. The MainWindow VM also has a OC of the same name. If I put instances of the read status class into the VM's OC, they show up in the user control's view. If I chance one of the object in the OC, only the progress bar changes. I cannot change either of the strings. It has to be a binding problem of some sort. Here is a link WPF Test App to a small test app that contains the DLLs needed for the progress bar.
This is the read status class:
public class FileLoadClass
{
public string FileName { get; set; }
public ProgressBarEdit ProgressBar { get; set; }
public string Status { get; set; }
}
The user control:
<UserControl
x:Class="WpfApp4.MultiFileReadControl"
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:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:local="clr-namespace:WpfApp4"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Grid>
<ListView
Name="LogListView"
Height="220"
HorizontalContentAlignment="Center"
FontSize="10"
ItemsSource="{Binding FilesToProcess}"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListView.View>
<GridView>
<GridViewColumn
DisplayMemberBinding="{Binding FileName}"
Header="File Name" />
<GridViewColumn Header="Progress">
<GridViewColumn.CellTemplate>
<DataTemplate>
<dxe:ProgressBarEdit
Width="300"
Height="30"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Red"
ContentDisplayMode="Value"
DisplayFormatString="{}{0}%"
Foreground="#FFFCF5F5"
Maximum="100"
Minimum="0"
ProgressBrush="DarkGreen"
Value="{Binding ProgressBar.Value}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
DisplayMemberBinding="{Binding Status}"
Header="Status" />
</GridView>
</ListView.View>
</ListView>
</Grid>
The VM:
namespace WpfApp4
{ internal class MainWindowVM {
private Dispatcher _dispatcher;
private ObservableCollection<FileLoadClass> _filesToProcess;
private MultiFileReadControl _multiFileReadControl;
private MainWindow _parent;
private Random _rnd;
public ObservableCollection<FileLoadClass> FilesToProcess
{
get => _filesToProcess;
set { _filesToProcess = value;}
}
public MainWindowVM(MainWindow parent, Dispatcher disp)
{
_parent = parent;
_dispatcher = disp;
_rnd = new Random();
}
internal void RndClick(object sender, RoutedEventArgs e)
{
FileLoadClass x = FilesToProcess[1];
x.ProgressBar.Value = _rnd.Next(100);
x.Status = "Processing";
FilesToProcess[1] = x;
}
internal void StartClick(object sender, RoutedEventArgs e)
{
_multiFileReadControl = new MultiFileReadControl();
DockPanel dp = _parent.dpMasterPanel;
DockPanel.SetDock(_multiFileReadControl, Dock.Top);
dp.Children.Add(_multiFileReadControl);
FilesToProcess = new ObservableCollection<FileLoadClass>();
FileLoadClass fileLoadClass = new FileLoadClass()
{
FileName = "File #1",
ProgressBar = new DevExpress.Xpf.Editors.ProgressBarEdit() { Value = 0 },
Status = "Waiting"
};
FilesToProcess.Add(fileLoadClass);
fileLoadClass = new FileLoadClass()
{
FileName = "File #2",
ProgressBar = new DevExpress.Xpf.Editors.ProgressBarEdit() { Value = 0 },
Status = "Waiting"
};
FilesToProcess.Add(fileLoadClass);
fileLoadClass = new FileLoadClass()
{
FileName = "File #3",
ProgressBar = new DevExpress.Xpf.Editors.ProgressBarEdit() { Value = 0 },
Status = "Waiting"
};
FilesToProcess.Add(fileLoadClass);
}
}
} The Main Window xaml and cs
<Window
x:Class="WpfApp4.MainWindow"
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:local="clr-namespace:WpfApp4"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<DockPanel Name="dpMasterPanel">
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
<Button
Width="65"
Height="50"
Margin="0,0,20,0"
HorizontalAlignment="Left"
Background="Firebrick"
Click="Start_Click"
Foreground="AntiqueWhite">
<TextBlock
Width="50"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="Start"
TextAlignment="Center"
TextWrapping="Wrap" />
</Button>
<Button
Width="70"
Height="50"
HorizontalAlignment="Left"
Background="Firebrick"
Click="Rnd_Click"
Foreground="AntiqueWhite">
<TextBlock
Width="50"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="Set Random Number"
TextAlignment="Center"
TextWrapping="Wrap" />
</Button>
</StackPanel>
</DockPanel>
namespace WpfApp4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private MainWindowVM _vm;
public MainWindow()
{
InitializeComponent();
_vm = new MainWindowVM(this, Dispatcher);
this.DataContext = _vm;
}
private void Start_Click(object sender, RoutedEventArgs e)
{
_vm.StartClick(sender, e);
}
private void Rnd_Click(object sender, RoutedEventArgs e)
{
_vm.RndClick(sender, e);
}
}
}
What is suspicious is the user control dependency property is never called. The data context is set in the MainWindow cs file to be the VM. Clicking the Start button creates the control and fills in data in the VM's OC.
Clicking the Set Random Number button should change the progress bar and the status text. Only the status bar changes:
Thanks.