I cannot for the life of me figure out why I cannot create my class in this dictionary. Intellisense isn't picking up my WindowCommand<T> class. I checked the Assembly name and it appears to be correct, no typos in the namespace either. What's making it choke?
WindowCommand.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using Ninject;
using Premier;
using Premier.View;
namespace Premier.Command
{
public class WindowCommand<T> : Command where T : Window
{
private Func<bool> focus;
private int instantiationCount;
public bool IsDialog { get; set; }
public bool Multiple { get; set; }
public WindowCommand()
{
}
public override bool CanExecute(object parameter)
{
return true;
}
public override void Execute(object parameter)
{
var instantiatedOnce = instantiationCount > 0;
if (!Multiple && instantiatedOnce)
{
focus();
return;
}
instantiationCount++;
var w = App.Kernel.Get<T>();
w.Closed += (s, e) => instantiationCount--;
focus = w.Focus;
if (IsDialog)
w.ShowDialog();
else
w.Show();
}
}
}
Windows.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:c="clr-namespace:Premier.Command;assembly=PremierAutoDataExtractor"
xmlns:v="clr-namespace:Premier.View;assembly=PremierAutoDataExtractor"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<c:WindowCommand x:Key="ReportsPurchased" x:TypeArguments="v:PurchasedReportsView" />
</ResourceDictionary>
x:TypeArguments XAML directive is not supported in XAML 2006 (xml namespace http://schemas.microsoft.com/winfx/2006/xaml/presentation) on non-root XAML elements. If you want to use x:TypeArguments on a non-root XAML element, you should use XAML2009 (xml namespace http://schemas.microsoft.com/netfx/2009/xaml/presentation). However, again it is only supported for non-complied loose XAML.
Text from MSDN Page:
In WPF and when targeting .NET Framework 4, you can use XAML 2009
features together with x:TypeArguments but only for loose XAML (XAML
that is not markup-compiled). Markup-compiled XAML for WPF and the
BAML form of XAML do not currently support the XAML 2009 keywords and
features. If you need to markup compile the XAML, you must operate
under the restrictions noted in the "XAML 2006 and WPF Generic XAML
Usages" section.
So, I am afraid, you cannot use your WindowCommand in a resource dictionary.
Link to MSDN page for more information on x:TypeArguments directive.
Related
Goal:
I want to display an ImageButton with an image just like this:
The current solution is working but I can only choose to set a single image hardcoded into xaml.
For this purpose I have already prepared multiple things:
Current Situation
I have added the image and set it as "Build Action: Embedded Resource"
I have added ImageResourceExtension just as suggested online for use in xaml:
using System;
using System.Reflection;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Bitconomy.resources
{
[ContentProperty(nameof(Source))]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Source == null)
{
return null;
}
// Do your translation lookup here, using whatever method you require
var imageSource = ImageSource.FromResource(Source, typeof(ImageResourceExtension).GetTypeInfo().Assembly);
return imageSource;
}
}
}
I have added reference to the ImageResourceExtension/resources in xaml:
xmlns:resources="clr-namespace:Bitconomy.resources"
I have added the image resource to the ImageButton:
<ImageButton x:Name="MiningButton" Grid.Row="0" Source="{resources:ImageResource Bitconomy.resources.images.mines.stone_mine.jpg}" ></ImageButton>
The result is the one shown in the top under the Goal section. fine so far.
Issue
I would like to set up the mines on the go. I have prepared a "mining_view.xaml". Within "mining_view.xaml.cs", I have added code to configure the mine, eg. for stone, iron, or whatever it will be. I want to have different images for each mine.
I have had a similar question in the past available on my stack overflow but it was for desktop use. I was shocked how different mobile development is after all. Similar but not the same.
I'd be very happy if you could help me figure out on how to set the image source in code so it will work in both, android and ios.
public void ConfigureMine(string ItemType)
{
this.MiningButton.Source = new ImageSource.FromResource("resources:ImageResource Bitconomy.resources.images.mines.stone_mine.jpg");
// or sth like that?
this.MiningButton.Source = resources.ImageResourceExtension.ProvideValue(SomeProvider?)
}
create an image in xaml. Assign an x:Name property to select the image from code:
<Image x:Name="Mine_Image" Grid.Column="0" Grid.Row="0" Aspect="AspectFill"></Image>
You will need an resource extension:
using System;
using System.Reflection;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Bitconomy.resources
{
[ContentProperty(nameof(Source))]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
public object ProvideValue(IServiceProvider serviceProvider)
{
if (Source == null)
{
return null;
}
// Do your translation lookup here, using whatever method you require
var imageSource = ImageSource.FromResource(Source, typeof(ImageResourceExtension).GetTypeInfo().Assembly);
return imageSource;
}
public ImageSource GetImageSource(string resourcepath)
{
return ImageSource.FromResource(resourcepath, typeof(ImageResourceExtension).GetTypeInfo().Assembly);
}
}
}
add resource image
Set image to build action "Embedded Resource"
Change Image within form.xaml.cs (adjust the resource path for your needs):
this.Mine_Image.Source = Resources.GetImageSource("Bitconomy.resources.images.resources.Stone_mine.jpg");
====SOLVED====
Joe's answer was spot on and I was able to get this working using his advice. I basically just had to add the effect in my code behind and it worked.
Using information found on the net, I created a PlatformEffect for iOS that can be assigned to any element. It adjusts the view to take into account an iPhone notch, if present.
My problem is, I am unable to reference the platform effect in my XAML.
Theortically, given the code at the bottom of this message, I should be able to use the following to apply the effect:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Enterprise.View.Features.Authentication.LoginView"
xmlns:effect="clr-namespace:Enterprise.iOS.Effects">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentView BackgroundColor="Green">
<ContentView.Effects>
<effect:SafeAreaPaddingEffect />
</ContentView.Effects>
<Label Text="Hello, from XamarinHelp.com" />
</ContentView>
</Grid>
</ContentPage>
However, the effect reference cannot be resolved in the ContentPage declaration. I'm probably doing something wrong, but I'm not sure what it is. I have not found anything via searches that answer my question.
Any thoughts? Here is the PlatformEffect file (located under an Effects folder in the iOS solution):
using Enterprise.iOS.Effects;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ResolutionGroupName("Enterprise.iOS")]
[assembly: ExportEffect(typeof(SafeAreaPaddingEffect), nameof(SafeAreaPaddingEffect))]
namespace Enterprise.iOS.Effects
{
public class SafeAreaPaddingEffect : PlatformEffect
{
Thickness _padding;
protected override void OnAttached()
{
if (Element is Layout element)
{
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
{
_padding = element.Padding;
var insets =
UIApplication.SharedApplication.Windows[0].SafeAreaInsets; // Can't use KeyWindow this early
if (insets.Top > 0) // We have a notch
{
element.Padding = new Thickness(_padding.Left + insets.Left, _padding.Top + insets.Top,
_padding.Right + insets.Right, _padding.Bottom);
return;
}
}
// Uses a default Padding of 20. Could use an property to modify if you wanted.
element.Padding = new Thickness(_padding.Left, _padding.Top + 20, _padding.Right, _padding.Bottom);
}
}
protected override void OnDetached()
{
if (Element is Layout element)
{
element.Padding = _padding;
}
}
}
}
To implement an effect for usage in a XAML Xamarin Forms project the following classes might be defined:
MyEffects.EffectIds (namespace MyEffects, class name EffectIds) located in a Xamarin Forms or a Netstandard project (e.g. MyProject) to define the identifier of the Effect.
MyEffects.MyEffect (namespace MyEffects, class name MyEffect) located in a Xamarin Forms project or a Netstandard project (e.g. MyProject) to define the Xamarin Forms effect.
MyEffects.iOS.MyEffect (namespace MyEffects.iOS, class name MyEffect) located in an iOS project to implement the iOS effect.
Sample MyEffects.EffectIds:
using Xamarin.Forms;
[assembly: ResolutionGroupName(MyEffects.EffectIds.GroupName)]
namespace MyEffects
{
public class EffectIds
{
public const string GroupName = "MyEffects";
public static string MyEffect => typeof(MyEffect).FullName;
//another effect not defined here
public static string MyOtherEffect => typeof(MyOtherEffect).FullName;
...
Sample MyEffects.MyEffect:
using Xamarin.Forms;
namespace MyEffects
{
public class MyEffect : RoutingEffect
{
public MyEffect() : base(EffectIds.MyEffect) { }
}
}
Sample MyEffects.iOS.MyEffect:
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using PlatformEffects = MyEffects.iOS;
using RoutingEffects = MyEffects;
[assembly: ExportEffect(typeof(PlatformEffects.MyEffect), nameof(RoutingEffects.MyEffect))]
namespace MyEffects.iOS
{
public class MyEffect : PlatformEffect
{
protected override void OnAttached()
{
...
Sample usage in XAML:
<ContentPage
xmlns:effects="clr-namespace:MyEffects;assembly=MyProject"
...
<Entry ... >
<Entry.Effects>
<effects:MyEffect />
</Entry.Effects>
</Entry>
I was able to fix this by assigning the effect in the code behind. So the relevant XAML not looks like the following
<ContentView BackgroundColor="Green">
<Label x:Name="HelloLabel" Text="Hello, from XamarinHelp.com" />
</ContentView>
and in my code behind, I added the followin immediately after initializing the component
HelloLabel.Effects.Add(Effect.Resolve("Enterprise.iOS.Effects.SafeAreaPaddingEffect"));
In the Visual Studio Community MainPage.xaml.cs file containing the following code:
using System;
using System.Collections.Generic;
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;
using Windows.UI.Xaml.Media.Animation;
using System.Collections.ObjectModel;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace App2
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
Random random = new Random();
///private NavigationHelper navigationHelper; ///not needed in Visual Studio 2017
private ObservableDictionary defaultViewModel = new ObservableDictionary();
public MainPage()
{
this.InitializeComponent();
}
private void startButton_Click(object sender, RoutedEventArgs e)
{
AddEnemy();
}
private void AddEnemy()
{
ContentControl enemy = new ContentControl();
enemy.Template = Resources["EnemyTemplate"] as ControlTemplate;
AnimateEnemy(enemy, 0, playArea.ActualWidth - 100, "(Canvas.Left)");
AnimateEnemy(enemy, random.Next((int)playArea.ActualHeight - 100), random.Next((int)playArea.ActualHeight - 100), "(Canvas.Top)");
playArea.Children.Add(enemy);
}
private void AnimateEnemy(ContentControl enemy, double from, double to, string propertyToAnimate)
{
Storyboard storyboard = new Storyboard() { AutoReverse = true, RepeatBehavior = RepeatBehavior.Forever };
DoubleAnimation animation = new DoubleAnimation()
{
From = from,
To = to,
Duration = new Duration(TimeSpan.FromSeconds(random.Next(4, 6)))
};
Storyboard.SetTarget(animation, enemy);
Storyboard.SetTargetProperty(animation, propertyToAnimate);
storyboard.Children.Add(animation);
storyboard.Begin();
}
}
}
... the line
private ObservableDictionary defaultViewModel = new ObservableDictionary();
produces the following error message:
Error CS0246 The type or namespace name 'ObservableDictionary' could not
be found (are you missing a using directive or an assembly reference?)
What library am I supposed to include to make this error message go away?
I know that this question is too old, but Head First C# used a Common folder, that has this ReadMe:
The Common directory contains classes and XAML styles that simplify application development.
These are not merely convenient, but are required by most Visual
Studio project and item templates. If you need a variation on one of
the styles in StandardStyles it is recommended that you make a copy in
your own resource dictionary. When right-clicking on a styled control
in the design surface the context menu includes an option to Edit a
Copy to simplify this process.
Classes in the Common directory form part of your project and may be
further enhanced to meet your needs. Care should be taken when
altering existing methods and properties as incompatible changes will
require corresponding changes to code included in a variety of Visual
Studio templates. For example, additional pages added to your project
are written assuming that the original methods and properties in
Common classes are still present and that the names of the types have
not changed.
In the VS2013 solution common folder (there is a VS2012 too, with totally different classes) these are the cs files:
To use these classes you have to add:
using Save_the_Humans.Common;
HFC# had not once in the book cited or referred to these classes; I'm assuming that they were boilerplate code at that time; they wrap some Interfaces and Dictionaries:
public class ObservableDictionary : IObservableMap<string, object>
{
private class ObservableDictionaryChangedEventArgs : IMapChangedEventArgs<string>
{
public ObservableDictionaryChangedEventArgs(CollectionChange change, string key)
{
this.CollectionChange = change;
this.Key = key;
}
public CollectionChange CollectionChange { get; private set; }
public string Key { get; private set; }
...
You can get the C# code - not only the common folder - from them with the VS2012 version too or from my repository with only VS2013; from their repository you cannot open or import into VS2017 - at least I couldn't; mine is already fresh made with VS2017.
Hope it helps someone.
Based on this example at MSDN, I created a "non-generic custom collection class that derives from ObservableCollection, and constrains it to a specific type." This is used as the ItemsSource property of a listview control. This all works perfectly and the xaml design view displays the sample data I loaded into the custom collection class.
The problem occurs when I try to build the project; I get this error: "Error 1 Unknown type 'ThreadCollection' in XML namespace 'clr-namespace:Messaging_2._0;assembly=Messaging 2.0.WindowsPhone, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' C:\Users\Wesley\Source\Repos\Messenging 2.0\Messaging 2.0\Messaging 2.0\Messaging 2.0.WindowsPhone\MainPage.xaml 14 10 Messaging 2.0.WindowsPhone.
This error originates from the line <c:ThreadCollection x:Key="MainThreadCollection"/> of the xaml code below.
<Page
x:Class="Messaging_2._0.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Messaging_2._0"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:c="clr-namespace:Messaging_2._0"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<c:ThreadCollection x:Key="MainThreadCollection"/>
</Page.Resources>
<The code for the listview control is here, I haven't included it because it works as I expect.>
Here is the C# code behind referenced by the xaml:
using System;
using System.Collections.Generic;
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;
using System.Collections.ObjectModel;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace Messaging_2._0
{
/// <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 ThreadCollection MainThreadCollection = new ThreadCollection();
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
this.DataContext = this;
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached.
/// This parameter is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// TODO: Prepare page for display here.
// TODO: If your application contains multiple pages, ensure that you are
// handling the hardware Back button by registering for the
// Windows.Phone.UI.Input.HardwareButtons.BackPressed event.
// If you are using the NavigationHelper provided by some templates,
// this event is handled for you.
}
private void AddThread(object sender, RoutedEventArgs e)
{
MainThreadCollection.Add(new ThreadViewItem() { Name = "Tom Riddle", LatestMessage = "It worked!" });
}
}
public class ThreadCollection : ObservableCollection<ThreadViewItem>
{
public ThreadCollection()
: base()
{
Add(new ThreadViewItem() { Name = "Harry Potter", LatestMessage = "What's up?" });
}
}
public class ThreadViewItem
{
public String Name
{
get;
set;
}
public String LatestMessage
{
get;
set;
}
}
}
Because the design view previews the message from Harry Potter correctly, I think the problem is relatively minor, I just can't figure out what it is exactly.
I would place the ThreadCollection in its own file (preferably ThreadCollection.cs) and place it in its own namespace, like Messaging_2._0.Collections or something similar. Then point the xmlns:c to that namespace.
That will ensure that your class isn't affected by the automatic code generation involved when coding XAML.
If it doesn't solve your issue, the error text might at least be more helpful.
Edit: Example App -> http://www10.zippyshare.com/v/29730402/file.html
I'm programming an app for Windows 8 & Windows Phone. I'm using the portable class library (see this article http://blog.tattoocoder.com/2013/01/portable-mvvm-light-move-your-view.html).
My problem is: How can I open a second window by clicking on a button by using the MVVM-pattern? I don't want to do it in the behind-code.
My datacontext for the Windows 8 app looks in the xaml like this
DataContext="{Binding Main, Source={StaticResource Locator}}"
which uses the ViewModel of the PCL (= ViewModel for both, W8 & WP8)
xmlns:vm="using:Mvvm.PCL.ViewModel"
I don't know how to assign 2 datacontext to my MainPage.xaml, nor do I know how to assign my MainPage.xaml to the ViewModel for my Windows 8 app.
I've tried something like this:
Command="{Binding DisplayView}" CommandParameter="SecondView"
but the program uses the ViewModel for both platforms and I can't program there the windows-assignment for the specific platforms. (it should look something like this Opening multiple views by clicking button using MVVM silverlight approach ...)
To make it clear:
I have 2 projects.
Both MainWindows of the projects refer to the ViewModel of the "MainProject".
If I want to click on a button in my MainWindow, I want to open a new view, but I can only use the ViewModel for both projects, which means that I can't use any views of the 2 projects in my ViewModel of the "MainProject".
edit: I've seen that many people use ContentControl. (Still doesn't work. Btw im new to MVVM).
<ContentControl Grid.Row="2" Content="{Binding CurrentView}" IsTabStop="False" Margin="10" />
<Button Command="{Binding DisplayView}" CommandParameter="SecondView">
MainViewModel.cs (For both platforms)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Mvvm.PCL.Model;
#if NETFX_CORE
using Mvvm.Store.Views;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#endif
namespace Mvvm.PCL.ViewModel
{
public class MainViewModel : ViewModelBase, INotifyPropertyChanged
{
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
#if NETFX_CORE
DisplayView = new RelayCommand<string>(DisplayViewCommandExecute);
#endif
}
#region Commands
public RelayCommand<string> DisplayView { get; private set; }
#endregion
#if NETFX_CORE
#region CurrentView Property
public const string CurrentViewPropertyName = "CurrentView";
private Page _currentView;
public Page CurrentView
{
get { return _currentView; }
set
{
if (_currentView == value)
return;
_currentView = value;
RaisePropertyChanged(CurrentViewPropertyName);
}
}
private SecondView _secondview = new SecondView();
public SecondView SecondView
{
get
{
return _secondview;
}
}
#endregion
private void DisplayViewCommandExecute(string viewName)
{
switch (viewName)
{
case "SecondView":
CurrentView = _secondview;
var frame = (Frame)Window.Current.Content;
frame.Navigate(typeof(SecondView));
break;
}
}
#endif
}
}