OxyPlot Odd Marker Placement With LineSeries - marker

I am coding a basic Cumulative Moving Average LineSeries with the MarkerType = MarkerType.Circle. For some reason my Marker is ending up not on the line. Pan and Zoom are disabled on my Y axis. I have included a picture of it. Anyone know of a reason why it would be doing this?
This is how I'm adding the Series to the plot
<Grid x:Name="GridChart" Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Background="Yellow" Padding="4" FontWeight="Normal" FontSize="12" Visibility="Collapsed"/>
<oxy:Plot Grid.Row="1" x:Name="PlotStrikeTheoBasis" MouseDoubleClick="PlotStrikeTheoBasisOnMouseDoubleClick" Margin="5" LegendPlacement="Inside" MouseWheel="PlotStrikeTheoBasisOnMouseWheel">
<oxy:Plot.Annotations>
<oxy:LineAnnotation Type="Horizontal" Y="0"/>
</oxy:Plot.Annotations>
<oxy:Plot.Axes>
<oxy:LinearAxis Position="Left" x:Name="AxisQty" Title="Qty" IsZoomEnabled="False" IsPanEnabled="False" MinorTickSize="0"/>
<oxy:LinearAxis Position="Bottom" x:Name="AxixBasisPoints" Title="Basis Points" MinorTickSize="0" Maximum="{Binding Max, Mode=TwoWay}" Minimum="{Binding Min, Mode=TwoWay}" AbsoluteMaximum="200" AbsoluteMinimum="-200"/>
</oxy:Plot.Axes>
<oxy:LineSeries x:Name="LineSeriesMovingAverage" Visibility="{Binding MovingAverageQtyChecked, Converter={StaticResource BooleanVisibilityConverter}}" ItemsSource="{Binding MovingAverageDataSeriesSet}" DataFieldX="BasisPoints" DataFieldY="Quantity" Title="CMA" MarkerType="Cross" MarkerStroke="HotPink"/>
</oxy:Plot>
</Grid>
public partial class TheoBasisStrikeChartWindow : Window
{
private static readonly ILog Log = LogManager.Create();
private TheoBasisHistogramViewModel _viewModel;
internal TheoBasisHistogramViewModel TheoBasisHistogramViewModel
{
get { return _viewModel; }
set
{
_viewModel = value;
GridChart.DataContext = value;
}
}
public TheoBasisStrikeChartWindow()
{
InitializeComponent();
TheoBasisHistogramViewModel = new TheoBasisHistogramViewModel();
}
private void Refresh()
{
try
{
_viewModel.Refresh();
}
catch (Exception ex)
{
Log.Error(ex);
MessageWindow.Show(
"Error occurred loading Window. Please report to IT Staff",
"Error", MessageWindowImage.Error,
MessageWindowStartupLocation.CreateCenteredOn(this, this), MessageWindowButton.OK);
}
}
}
public class BasisPointsQty
{
public double BasisPoints { get; set; }
public double Quantity { get; set; }
public BasisPointsQty(double basisPoints, int quantity)
{
BasisPoints = basisPoints;
Quantity = quantity;
}
}
public class TheoBasisHistogramViewModel : PropertyChangedNotifier
{
public ObservableCollectionEx<BasisPointsQty> MovingAverageDataSeriesSet { get;}
public TheoBasisHistogramViewModel()
{
MovingAverageDataSeriesSet = new ObservableCollectionEx<BasisPointsQty>();
}
public void Refresh()
{
// Update MovingAverageDataSeriesSet here
}
}

Related

Need to create a FeetInches usercontrol in XAML

I am trying to create a UWP feet/inches control that takes a value in inches, and splits it into two fields, feet and inches. The control, when updated by the user, should update the backend viewmodel with the new inches value.
Requirements
Change the value in 1, then the values in 2 and 3 update
accordingly.
Change the value in 3, the values in 1 and 2 update accordingly
The way I have this written it gets into an endless loop. I am not even sure the FeetInches control is written properly. How would I change this to meet the above requirements?
Downloadable/runnable code is available in GitHub, but here it is inline per SO guidelines...
App.xaml
<Application x:Class="UWPFeetInches.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UWPFeetInches">
<Application.Resources>
<ResourceDictionary>
<local:NullDecimalConverter x:Key="NullDecimalConverter" />
</ResourceDictionary>
</Application.Resources>
</Application>
MainPage.xaml
<Page
x:Class="UWPFeetInches.MainPage"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="using:UWPFeetInches"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
Text="Enter Inches Value:"
Margin="0,50,10,0"
VerticalAlignment="Center" />
<TextBox Grid.Row="0" Grid.Column="1"
Margin="0,50,10,0"
Text="{x:Bind ViewModel.Inches, Mode=TwoWay, Converter={StaticResource NullDecimalConverter}}" />
<TextBlock Grid.Row="1" Grid.Column="0"
Margin="0,50,10,0"
Text="Inches Display:"/>
<TextBlock Grid.Row="1" Grid.Column="1"
Margin="0,50,10,0"
Text="{x:Bind ViewModel.InchesDisplay, Mode=TwoWay}"/>
<TextBlock Grid.Row="2" Grid.Column="0"
Text="Feet / Inches Control:"
Margin="0,50,10,0"
VerticalAlignment="Center" />
<local:FeetInches Grid.Row="2" Grid.Column="1"
Margin="0,50,10,0"
Value="{x:Bind ViewModel.Inches, Mode=TwoWay}" />
</Grid>
</Page>
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace UWPFeetInches
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.ViewModel = new InchesViewModel();
}
public InchesViewModel ViewModel { get; set; }
}
public class InchesViewModel : INotifyPropertyChanged
{
private decimal? _Inches;
public decimal? Inches
{
get { return _Inches; }
set
{
if (value != _Inches)
{
_Inches = value;
InchesDisplay = _Inches == null ? "{null}" : _Inches.ToString();
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(Inches)));
}
}
}
private string _InchesDisplay;
public string InchesDisplay
{
get { return _InchesDisplay; }
set
{
if (value != _InchesDisplay)
{
_InchesDisplay = value;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(InchesDisplay)));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
NullDecimalConverter.cs
using System;
using Windows.UI.Xaml.Data;
namespace UWPFeetInches
{
public sealed class NullDecimalConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is decimal m)
{
return m == 0 ? "" : m.ToString();
}
return "";
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
if (!string.IsNullOrWhiteSpace(value?.ToString()))
{
if (Decimal.TryParse(value.ToString(), out decimal m))
{
return m;
}
}
return null;
}
}
}
FeetInches.xaml
<UserControl
x:Class="UWPFeetInches.FeetInches"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:UWPFeetInches"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<StackPanel Orientation="Horizontal">
<TextBox Header="Feet"
Margin="0,0,10,0"
Text="{x:Bind Feet, Mode=TwoWay}" />
<TextBox Header="Inches"
Text="{x:Bind Inches, Mode=TwoWay, Converter={StaticResource NullDecimalConverter}}" />
</StackPanel>
</UserControl>
FeetInches.xaml.cs
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236
namespace UWPFeetInches
{
public sealed partial class FeetInches : UserControl
{
public FeetInches()
{
this.InitializeComponent();
}
#region Feet
public int Feet
{
get { return (int)GetValue(FeetProperty); }
set
{
SetValue(FeetProperty, value);
}
}
public static readonly DependencyProperty FeetProperty = DependencyProperty.Register(nameof(Feet), typeof(int), typeof(FeetInches), new PropertyMetadata(0, OnPropertyChanged));
#endregion
#region Inches
public decimal Inches
{
get { return (decimal)GetValue(InchesProperty); }
set
{
SetValue(InchesProperty, value);
}
}
public static readonly DependencyProperty InchesProperty = DependencyProperty.Register(nameof(Inches), typeof(decimal), typeof(FeetInches), new PropertyMetadata(0M, OnPropertyChanged));
#endregion
#region Value
public decimal? Value
{
get { return (decimal)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(nameof(Value), typeof(decimal?), typeof(FeetInches), new PropertyMetadata(null, ValueOnPropertyChanged));
#endregion
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as FeetInches;
control.Value = control.Feet * 12 + control.Inches;
}
private static void ValueOnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as FeetInches;
var inches = control.Value;
control.Feet = inches.HasValue ? (int)(inches.Value / 12M) : 0;
control.Inches = inches.HasValue ? inches.Value - (control.Feet * 12M) : 0M;
}
}
}
When you subscribe the PropertyChanged event for the three dependency properties, it will get into an endless loop. You could try to subscribe the LostFocus event of TextBox in FeetInches.xaml to replace your OnPropertyChanged event for your Feet and Inches properties, in that case, it won't get into an endless loop. For example:
.xaml:
<TextBox Header="Feet"
Margin="0,0,10,0"
x:Name="MyFeet"
Text="{x:Bind Feet, Mode=TwoWay}" LostFocus="TextBox_LostFocus"/>
<TextBox Header="Inches"
x:Name="MyInches"
Text="{x:Bind Inches, Mode=TwoWay, Converter={StaticResource NullDecimalConverter}}" LostFocus="TextBox_LostFocus"/>
.cs:
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
var textbox = sender as TextBox;
Decimal.TryParse(textbox.Text, out decimal m);
if (textbox.Name.Equals("MyFeet"))
{
this.Value = m * 12 + this.Inches;
}
else
{
this.Value = this.Feet * 12 + m;
}
}
When triggered the LostFocus event, the property bound with the Text of TextBox has not changed, so you need to use the value of Text directly instead of the Feet/Inches property and you need to judge which TextBox triggers this event.
Or if you still want to use OnPropertyChanged event for Feet and Inches properties instead of LostFocus event, you can declare a property(e.g. bool valueChanged) to limit the calling of ValueOnPropertyChanged and OnPropertyChanged event.
.cs:
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (valueChanged == false) {
var control = d as FeetInches;
control.Value = control.Feet * 12 + control.Inches;
}
}
private static bool valueChanged = false;
private static void ValueOnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
valueChanged = true;
var control = d as FeetInches;
var inches = control.Value;
control.Feet = inches.HasValue ? (int)(inches.Value / 12M) : 0;
control.Inches = inches.HasValue ? inches.Value - (control.Feet * 12M) : 0M;
valueChanged = false;
}
Update:
You can use the Property property from DependencyPropertyChangedEventArgs data to check which dependency property changes.
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.Property == FeetProperty) {
//do something
}
else{
//do something
}
}

Binding value is not updating on entry control from other xaml

I have an entry control in my XAML where I set the initial value on page appear through data binding. Initially the value is appearing but when I am updating it from another view model it is not getting updated on UI.
Below is the XAML code and XAML.CS
<ListView
x:Name="workList"
Grid.Row="2"
SeparatorColor="{DynamicResource AccentColor}"
ItemsSource="{ Binding WorkItems }"
Margin="5"
CachingStrategy="RecycleElement"
RowHeight="440"
SeparatorVisibility="Default"
SelectionMode="None"
HasUnevenRows="False">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<local:LoadItemPutawayTemplate />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-
compatibility/2006"
mc:Ignorable="d"
x:Class="Sanipex.LoadItemPutawayTemplate">
<Grid
RowSpacing="0"
Padding="0"
Margin="0,10,0,0"
>
<Grid.RowDefinitions>
<RowDefinition
Height="*" />
</Grid.RowDefinitions>
<Entry
x:Name="OverrideLoc"
Grid.Row="0"
TextColor="Black"
WidthRequest="110"
Text="{Binding toLocation}"
grial:EntryProperties.BorderCornerRadius="10"
grial:EntryProperties.BorderStyle="RoundRect"
grial:EntryProperties.BorderColor="Black"
HorizontalOptions="StartAndExpand"
VerticalOptions="Center"
Focused="OverrideLoc_Focused"
TextChanged="OverrideLoc_TextChanged"
grial:EntryProperties.HorizontalPadding="5"
FontAttributes="Bold"
PlaceholderColor="Black"
FontSize="20"/>
</Grid>
public partial class ItemPutAway : ContentPage
{
private static ItemPutAwayViewModel obj;
public ItemPutAway()
{
InitializeComponent();
obj = new ItemPutAwayViewModel();
BindingContext = obj;
}
public static ItemPutAwayViewModel itemPutAwayViewModel
{
get
{
return obj;
}
}
protected override async void OnAppearing()
{
obj.LoadData();
}
}
Below is my first view model code
public class ItemPutAwayViewModel : INotifyPropertyChanged
{
private IList<WorkItem> workItems;
public event PropertyChangedEventHandler PropertyChanged;
public string ltoLocation;
public string toLocation
{
get => ltoLocation;
set
{
ltoLocation = value;
OnPropertyChanged(nameof(toLocation));
}
}
public IList<WorkItem> WorkItems
{
get => workItems;
set
{
workItems = value;
OnPropertyChanged(nameof(WorkItems));
}
}
public void LoadData()
{
WorkItems = App.dataManager.GetItemPutAwayWorks();
}
public void setLocation(string _location)
{
toLocation = _location;
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Below is the code through which I am trying to update the toLocation binding value to different value from another XAML page as below:
public partial class AvailableLocationsPopUp : PopupPage
{
private static AvailableLocationViewModel obj;
public AvailableLocationsPopUp(WorkItem _workItem)
{
InitializeComponent();
obj = new AvailableLocationViewModel(gWorkItem.itemid);
BindingContext = obj;
}
private void OnClose(object sender, EventArgs e)
{
PopupNavigation.Instance.PopAsync();
}
private void ListView_ItemTapped(object sender, ItemTappedEventArgs e)
{
Location content = e.Item as Location;
ItemPutAway.itemPutAwayViewModel.setLocation("ABC-XYZ");
PopupNavigation.Instance.PopAsync();
}
}
As I mentioned in the discussion, you have to also implement the INotifyPropertyChanged interface of the class WorkItem.
Implement INotifyPropertyChanged in ItemPutAwayViewModel will only help for changes in the WorkItems(like add or remove one WorkItem), not the changes inside the WorkItem.
So, the code should be:
public class WorkItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _toLocation;
public string toLocation
{
get => _toLocation;
set
{
_toLocation = value;
NotifyPropertyChanged();
}
}
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

How to access the parent viewmodel from inside a ListView.ItemTemplate?

I have this simple ListView filled from an ObservableCollection. Once the list is bound, I would like to access the parent vm view model from inside this ItemTemplate so that I can bind the command called cmd_delete_mesh. How is this done for a UWP Xaml app (not wpf)?
<ListView x:Name="mesh_list" SelectedItem="{x:Bind vm.selected_mesh, Mode=TwoWay}" ItemsSource="{x:Bind vm.meshes}">
<ListView.ItemTemplate>
<DataTemplate>
<ListViewItem>
<Button Command="{Binding cmd_delete_mesh}"/>
You can do like so:
<ListView x:Name="mesh_list" SelectedItem="{x:Bind vm.selected_mesh, Mode=TwoWay}" ItemsSource="{x:Bind vm.meshes}">
<ListView.ItemTemplate>
<DataTemplate>
<ListViewItem>
<Button Command="{Binding ElementName=mesh_list, Path=DataContext.vm.cmd_delete_mesh}"/>
I do this from code unfortunately... I’ll post an example of my code soon
You could define your command in your model and declare an event in it. In your ViewModel, when you initialize the 'meshes' collection, you could register this event for every item in this collection. Then, when the command is executed, you just need to raise the event and do some operations in its event handler.
I made a simple code sample for your reference:
<ListView x:Name="mesh_list" SelectedItem="{x:Bind ViewModel.selected_mesh, Mode=TwoWay}" ItemsSource="{x:Bind ViewModel.meshes,Mode=OneWay}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:SubTest">
<ListViewItem>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{x:Bind Name }"></TextBlock>
<Button Command="{x:Bind cmd_delete_mesh}" Content="delete"/>
</StackPanel>
</ListViewItem>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
ViewModel = new Test("test data");
}
private Test ViewModel { get; set; }
}
public class Test : ViewModelBase
{
public string Name { get; set; }
private SubTest _selected_mesh;
public SubTest selected_mesh
{
get { return _selected_mesh; }
set
{
if (_selected_mesh != value)
{
_selected_mesh = value;
RaisePropertyChanged("selected_mesh");
}
}
}
public ObservableCollection<SubTest> meshes { get; set; } = new ObservableCollection<SubTest>();
public Test(string name)
{
this.Name = name;
for (int i = 0; i < 10; i++)
{
var sub = new SubTest() { Name = "String " + i };
sub.DeleteParentItem += Test_DeleteParentItem;
meshes.Add(sub);
}
}
private void Test_DeleteParentItem()
{
if (selected_mesh != null)
{
DeleteItem(selected_mesh);
}
}
private void DeleteItem(SubTest subTest)
{
//TODO...
}
}
public class SubTest
{
public RelayCommand cmd_delete_mesh { get; set; }
public string Name { get; set; }
public event Action DeleteParentItem;
public SubTest()
{
cmd_delete_mesh = new RelayCommand(DeleteItem);
}
private void DeleteItem()
{
if (DeleteParentItem != null)
{
DeleteParentItem.Invoke();
}
}
}
Please note that the ViewModelBase and RelayCommand are from mvvmlight.
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;

UWP Binding to a property

I am making a UWP and cannot correctly grasp DataBinding and INotifyPropertyChanged
I am trying to bind some TextBox in a ContentDialog to properties in my code-behind cs file.
Here's my view model:
class UserViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public string _fname { get; set; }
public string _lname { get; set; }
public string Fname
{
get { return _fname; }
set
{
_fname = value;
this.OnPropertyChanged();
}
}
public string Lname
{
get { return _lname; }
set
{
_lname = value;
this.OnPropertyChanged();
}
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Code behind:
public sealed partial class MainPage : Page
{
UserViewModel User { get; set; }
public MainPage()
{
this.InitializeComponent();
User = new UserViewModel();
}
....
....
private void SomeButton_Click(object sender, TappedRoutedEventArgs e)
{
//GetUserDetails is a static method that returns UserViewModel
User = UserStore.GetUserDetails();
//show the content dialog
ContentDialogResult result = await UpdateUserDialog.ShowAsync();
}
}
Here's the XAML for the ContentDialog:
<ContentDialog Name="UpdateUserDialog">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
Name="tbFirstNameUpdate"
Text="{x:Bind Path=User.Fname, Mode=OneWay}"
Style="{StaticResource SignUpTextBox}"/>
<TextBox Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
Name="tbLastNameUpdate"
Text="{x:Bind Path=User.Lname, Mode=OneWay}"
Style="{StaticResource SignUpTextBox}"/>
</ContentDialog>
NOTE: Binding works well when I initialize the view model in the MainPage constructor itself like this:
User = new UserViewModel { Fname = "name", Lname = "name" };
You don't fire a PropertyChanged event when you replace the value of the User property with a new view model instance.
You may however simply replace
User = UserStore.GetUserDetails();
by
var user = UserStore.GetUserDetails();
User.Fname = user.Fname;
User.Lname = user.Lname;
and hence update the existing instance of your view model.
You should set the DataContext property to the view model instance:
public MainPage()
{
this.InitializeComponent();
User = new UserViewModel();
DataContext = User;
}
See: https://learn.microsoft.com/en-us/windows/uwp/data-binding/data-binding-in-depth

Caliburn Micro Win8.1 App - No target found for method X

I'm a xaml novice and pretty new to WPF/Store apps. I tried to create a simple example of Caliburn Micro (compiled on the recent code) for a Windows 8.1 Store app. But I was unable to get it running as since yesterday I'm getting the error - I did tried the samples under the source I'd downloaded, they just work fine. Same I tried to create from scratch, it throws the aforementioned exception.
Here is the code of the entire solution, please correct me if I've configured/used it wrong!
CalMicSample\App.xaml:
<caliburn:CaliburnApplication
x:Class="CalMicSample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:caliburn="using:Caliburn.Micro"
RequestedTheme="Light">
</caliburn:CaliburnApplication>
CalMicSample\App.xaml.cs
using Caliburn.Micro;
using CalMicSample.ViewModels;
using CalMicSample.Views;
using System;
using System.Collections.Generic;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml.Controls;
namespace CalMicSample
{
public sealed partial class App
{
private WinRTContainer container;
private INavigationService navigationService;
public App()
{
InitializeComponent();
}
protected override void Configure()
{
LogManager.GetLog = t => new DebugLog(t);
container = new WinRTContainer();
container.RegisterWinRTServices();
container.RegisterSharingService();
container
.PerRequest<MyTestViewModel>();
PrepareViewFirst();
}
protected override object GetInstance(Type service, string key)
{
var instance = container.GetInstance(service, key);
if (instance != null)
return instance;
throw new Exception("Could not locate any instances.");
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
protected override void PrepareViewFirst(Frame rootFrame)
{
navigationService = container.RegisterNavigationService(rootFrame);
}
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
Initialize();
var resumed = false;
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
resumed = navigationService.ResumeState();
}
if (!resumed)
DisplayRootView<MyTestView>();
}
}
}
CalMicSample\Helpers\ViewModelHelper.cs
using Caliburn.Micro;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace CalMicSample.Helpers
{
public static class ViewModelHelper
{
public static bool Set<TProperty>(
this INotifyPropertyChangedEx This,
ref TProperty backingField,
TProperty newValue,
[CallerMemberName] string propertyName = null)
{
if (This == null)
throw new ArgumentNullException("This");
if (string.IsNullOrEmpty(propertyName))
throw new ArgumentNullException("propertyName");
if (EqualityComparer<TProperty>.Default.Equals(backingField, newValue))
return false;
backingField = newValue;
This.NotifyOfPropertyChange(propertyName);
return true;
}
}
}
CalMicSample\Models\MonkeyMood.cs
namespace CalMicSample.Models
{
public class MonkeyMood
{
public string Message { get; set; }
public string ImagePath { get; set; }
}
}
CalMicSample\ViewModels\MyTestViewModel.cs
using Caliburn.Micro;
using CalMicSample.Helpers;
using CalMicSample.Models;
using System;
namespace CalMicSample.ViewModels
{
public class MyTestViewModel : ViewModelBase
{
private string food;
private MonkeyMood mood;
public MyTestViewModel(INavigationService navigationService)
: base(navigationService)
{
}
public string Food
{
get
{
return food;
}
set
{
this.Set(ref food, value);
}
}
public MonkeyMood Mood
{
get
{
return mood;
}
set
{
this.Set(ref mood, value);
}
}
public void FeedMonkey(string monkeyFood)
{
if (string.Compare(Food, "banana", StringComparison.CurrentCultureIgnoreCase) == 0)
{
Mood = new MonkeyMood();
Mood.Message = "Monkey is happy!";
Mood.ImagePath = #"D:\Tryouts\CaliburnMicroSample\CalMicSample\CalMicSample\Assets\monkey-happy.jpg";
}
else
{
Mood = new MonkeyMood();
Mood.Message = "Monkey is unhappy";
Mood.ImagePath = #"D:\Tryouts\CaliburnMicroSample\CalMicSample\CalMicSample\Assets\monkeysad.jpg";
}
}
public bool CanFeedMonkey(string monkeyFood)
{
return !string.IsNullOrWhiteSpace(monkeyFood);
}
}
}
CalMicSample\ViewModels\ViewModelBase.cs
using Caliburn.Micro;
namespace CalMicSample.ViewModels
{
public abstract class ViewModelBase : Screen
{
private readonly INavigationService navigationService;
protected ViewModelBase(INavigationService navigationService)
{
this.navigationService = navigationService;
}
public void GoBack()
{
navigationService.GoBack();
}
public bool CanGoBack
{
get
{
return navigationService.CanGoBack;
}
}
}
}
CalMicSample\Views\MyTestView.xaml
<Page
x:Class="CalMicSample.Views.MyTestView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CalMicSample.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:caliburn="using:Caliburn.Micro"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="171*"/>
<RowDefinition Height="86*"/>
<RowDefinition Height="382*"/>
<RowDefinition Height="129*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="172*"/>
<ColumnDefinition Width="328*"/>
<ColumnDefinition Width="183*"/>
</Grid.ColumnDefinitions>
<Button x:Name="FeedMonkey" Content="Feed" caliburn:Message.Attach="FeedMonkey" Grid.Column="2" HorizontalAlignment="Left" Height="72" Margin="7,7,0,0" Grid.Row="1" VerticalAlignment="Top" Width="138" FontSize="36"/>
<TextBox x:Name="txtFood" Grid.Column="1" HorizontalAlignment="Left" Height="66" Margin="10,10,0,0" Grid.Row="1" TextWrapping="Wrap" Text="Banana" VerticalAlignment="Top" Width="636" FontSize="36"/>
<TextBlock x:Name="lblFeedMonkey" Grid.Column="1" HorizontalAlignment="Left" Margin="10,119,0,5" TextWrapping="Wrap" Text="Give some food to the monkey" Width="636" FontSize="36" FontWeight="Bold"/>
<TextBlock x:Name="lblMonkeyMood" Grid.Column="1" HorizontalAlignment="Center" Margin="59,25,37,10" Grid.Row="3" TextWrapping="Wrap" VerticalAlignment="Center" Height="94" Width="560" FontSize="72"/>
<Image x:Name="imgMonkey" Grid.Column="1" HorizontalAlignment="Left" Height="362" Margin="10,10,0,0" Grid.Row="2" VerticalAlignment="Top" Width="636"/>
</Grid>
</Page>
CalMicSample\Views\MyTestView.xaml.cs
using Windows.UI.Xaml.Controls;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace CalMicSample.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MyTestView : Page
{
public MyTestView()
{
this.InitializeComponent();
}
}
}
Your feedmonkey method in your vm wants a string parameter, but your not supplying one when attaching to your button. See here for more info: http://caliburnmicro.codeplex.com/wikipage?title=Cheat%20Sheet
Rob is correct, you need to match the method signature of your FeedMonkey(string monkeyFood), at the moment so `Caliburn.Micro' is unable to locate the correct method.
You'd want to use something like:
// You wouldn't want to use a hard coded string, but this is how you'd do it.
caliburn:Message.Attach="FeedMonkey('banana')"
// Or you can pass some of the special values linked in Rob's answer (the Caliburn docs).
// You'd probably want a sub property, depending on what it was you were passing.
caliburn:Message.Attach="FeedMonkey($dataContext)"