Reputation: 71
I am new to MVVM and XAML and I’ve run into a road block. Any help you can give is greatly appreciated! We are using WPF/MVVM and XAML to dynamically create buttons on a WrapPanel. The buttons appear as normal and are bound to an observable collection (RigDataSrceClass). (The observable collection is fed by a call to a SQL stored Proc and then updated with new button status (Background and Foreground colors) by a Subscription to a Pub/Sub.)
The data is correctly getting into the Collection but the buttons backgrounds/foregrounds do not update – they forever stay the original color. I need all the buttons to update with new Status values as the status is changed in the RigDataSrceClass.
I’ve tried about 8 different ways to get the button colors to update, including a Style Template on mouse over event (which only changes the font/foreground color and doesnt take updates from the datasource), cs code-behind to build and update the buttons (This works in non-MVVM but in MVVM the RigDataSrceClass is not available in the View), and endless amounts of binding of templates and controls, all with no effect what-so-ever. Plus these didn’t work:
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
this.Content = new ContentControl(); //Wipes out my buttons!
RigButtonsClassControl.InvalidateArrange(); // No effect
this.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate); // No effect
CommandManager.InvalidateRequerySuggested(); // No effect
}
The xaml follows:
<Grid>
<ItemsControl x:Name="RigButtonsClassControl" ItemsSource="{Binding RigDataSrceClass, Mode=OneWay}" Grid.Row="1" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Tag="{Binding Id}" x:Name="RigBtn" Content="{Binding RigContent, Mode=TwoWay}" Style="{StaticResource myStyle}" Click="Button_RefreshControl_Click" FontWeight="Bold" Width="33" MaxHeight="33" Margin="1" Background="{Binding RigStatus}" Foreground="{Binding RigStatusForeground}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
The View Model cs code follows:
public class RigsViewModel : ViewModelBase<IMainView>, IPublishing
{
ISubscription _subscriptionProxy;
string _endpoint = string.Empty;
List<String> rigSubscribedList = new List<String>();
String txtTopicName;
private ObservableCollection<RigButtonDataModelClass> _ObservCollRigData = new ObservableCollection<RigButtonDataModelClass>();
public ObservableCollection<RigButtonDataModelClass> RigDataSrceClass
{
get { return _ObservCollRigData; }
}
…
}
public RigsViewModel()
: base(new RigsWindow())
{
this.ws_context = new FlexViewWCF.EntitiesModelServiceClient();
this.rigFilter = string.Empty;
this.isFilteringActive = false;
this.Status = string.Empty;
_endpoint = ConfigurationManager.AppSettings["EndpointAddress"];
MakeProxy(_endpoint, this);
txtTopicName = "R464RigStatus,R469RigStatus,R472RigStatus,R496RigStatus,R498RigStatus,R514RigStatus";
OnSubscribe();
this.RetrieveRigsToDisplay();
// var vm = DataContext as ViewModel;
// vm.Resources.Add(new Resource { Id = 1, Content = "Resource 1" });
foreach (FlexViewWCF.CurrentRigCustomerDto dto in this.RigsToDisplay)
{
RigButtonDataModelClass rbdmc = new RigButtonDataModelClass();
rbdmc.RigContent = dto.RigNumber;
rbdmc.RigCommand = null;
rbdmc.RigStatusForeground = "Black";
rbdmc.RigStatus = "LightGray"; //dto.Status;
RigDataSrceClass.Add(rbdmc);
}
//this.RigButtonsToDisplay = rigsToDisplay.
//RigButtonsToDisplay =
//MakeRigButtons();
}
And I update the data from the Subscription here: RigStatus is the new Background color and the Foreground is explicitly defined...
lock (rigsToDisplay)
{
foreach (FlexViewWCF.CurrentRigCustomerDto cusRig in rigsToDisplay)
{
if (cusRig.RigNumber == topicName.Substring(1, 3))
{
cusRig.Status = e.EventData.ToString();
break;
}
}
foreach (FlexView.ViewModels.RigButtonDataModelClass cusRig in RigDataSrceClass)
{
if (cusRig.RigContent == topicName.Substring(1, 3))
{
if (e.EventData.ToString() == "Black")
cusRig.RigStatusForeground = "White";
else
cusRig.RigStatusForeground = "Black";
cusRig.RigStatus = e.EventData.ToString();
break;
}
}
}
Thank you and best regards!!!
Upvotes: 0
Views: 142
Reputation: 43634
Does RigButtonDataModelClass
implement INotifyPropertyChanged
?
If not you will need to add it to your class and call NotifiyPropertyuChanged
on the properties required, this will notify the Xaml
that the binding value has changed and will update.
Quick Example:
public class RigButtonDataModelClass : INotifyPropertyChanged
{
private int _myProperty;
public int MyProperty
{
get { return _myProperty; }
set { _myProperty = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName]string propertyname = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
}
Upvotes: 1