Rider Code Completion for Autowired ViewModel (Prism) - c#

I'm working on a project that uses Prism for its client software. I have a UserControl XAML file that looks something like this:
<UserControl x:Class="UserModule.Frontend.UserListView"
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:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ListView ItemsSource="{Binding Users}"/>
</Grid>
</UserControl>
The actual XAML is a bit longer, but my question is:
Rider shows me a warning at the binding of the list view's ItemsSource property. I have a ViewModel that Prism injects correctly and I can see that the list has been populated. However, at design time, I can't see if the property exists, if I don't check for myself. At the same time, I get a warning in the ViewModel class, that the public getter of Users could be removed.
Is there a way to get code completion to recognize the autowired ViewModel with Prism?

You need to define the d:DataContext for your view. And while you're at it, vote for the feature...

Related

Binding WPF xaml to a ViewModel without constructing it

My WPF app doesn't use an app.xaml. I'm using MVVM, and construct the view and the viewmodel separately. I then pass the ViewModel to the View constructor and set the datacontext there.
I'd like to have Visual Studio be able to understand the viewmodel's properties for context clicking and such, but not have it construct its own DataContext when the view is set.
When I do this, it forces me to have a default constructor for MainViewModel, and then it calls that VM constructor when I construct the View.
<Window x:Class="Kraken.CopFeed.Windows.MainFeedView"
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:Windows="clr-namespace:MyProgram.MainApp.WpfWindows"
mc:Ignorable="d"
Title="Main App" Height="321.557" Width="652.922">
<Window.DataContext>
<Windows:MainViewModel />
</Window.DataContext>
How can I keep my existing implementation of constructing the V and VM separately, but get the XAML editor in Visual STudio to know of my ViewModel that will (eventually) be set as the data context?
I think you should be able to do this with d:DesignInstance, as in this question.
<Window
...etc...
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=MyViewModelNamespace:MyViewModel}"
>

UserControl DataContext defined at XAML page level

I defined a DataContext for a UserControl at XAML page level as follows (the last line being the relevant one):
<UserControl
x:Class="Sample.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data="using:Sample.Models"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="768"
d:DesignWidth="1024"
DataContext="data:TestDataCollection">
The aim is to be able to access the DataContext object in the page hosting the UserControl as follows, myUserControl being the x:Name for the UserControl.
TestDataCollection tdc = myUserControl.DataContext as TestDataCollection;
Everything is working fine with data binding and UI displaying and updating as expected on the UWP platform.
The only one problem is that the above code line is not returning the expected DataContext object. In fact, myUserControl.DataContext during debugging shows a string with a value "data:TestDataCollection" (same as in the above XAML code) rather than an object of type TestDataCollection.
Here is another strange thing: If I set the DataContext in codebehind as:
this.DataContext = new TestDataCollection();
the problem with be gone, i.e., (myUserControl.DataContext as TestDataCollection) returns the DataContext object as expected.
What am I doing wrong in setting the page DataContext in XAML?
By using DataContext="data:TestDataCollection", you're doing nothing more than setting a string value. If you want a viewmodel object to be set, you have to use following syntax:
<UserControl
x:Class="Sample.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data="using:Sample.Models"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="768"
d:DesignWidth="1024">
<UserControl.DataContext>
<data:TestDataCollection />
</UserControl.DataContext>
</UserControl>
Note that your usercontrol will also inherit a DataContext from the page it's used on. So in most scenarios it's not necessary to set it explicitly in your control, while you will still be able to access it in code behind (as it's set by the page implicitly).

ComboBox databinding to window background

Very new to WPF and c# here. I'm interested in having a ComboBox with different color options that will update the window's Background when an option is selected.
I want to do this via DataBinding, but I'm a noob and can't get it right. This is what I have.
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
Background="{Binding SelectedValue,ElementName=combo,UpdateSourceTrigger=PropertyChanged}">
<StackPanel>
<ComboBox Name="combo">
<ComboBoxItem>lightcoral</ComboBoxItem>
<ComboBoxItem>khaki</ComboBoxItem>
</ComboBox>
</StackPanel>
</Window>
And the default MainWindow.xaml.cs (I haven't touched it since I created the project)
Thanks, let me know if you need any more info!
One possible way to achieve this is to put items of type string in your ComboBox, as opposed to ComboBoxItems:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Background="{Binding SelectedItem, ElementName=combo}">
<ComboBox VerticalAlignment="Center" HorizontalAlignment="Center" x:Name="combo">
<sys:String>Yellow</sys:String>
<sys:String>Green</sys:String>
<sys:String>Red</sys:String>
<sys:String>Blue</sys:String>
</ComboBox>
</Window>
Notice that I declared the xmlns:sys XAML Namespace that points to the System CLR namespace in the mscorlib.dll assembly. This is where the class System.String is defined, and you need that to be able to use the class in XAML.
Also notice that I'm binding to SelectedItem as opposed to SelectedValue, this is because your ComboBox does not have SelectedValuePath, and WPF doesn't have the notion of the SelectedValue because it does not know how to "retrieve the value" from each of it's items.
Also notice that UpdateSourceTrigger is removed because it does not make any sense. UpdateSourceTrigger determines the way the Binding source is updated, not the target. Read about DataBinding on MSDN to understand the terminology here.
The reason that using a String works and using a ComboBoxItem does not is because the default Type Converter for the Brush class (which is the type of the Window's Background) "understands" how to convert from a string, but not from a ComboBoxItem.

WPF: nested designData

I have the following simplified element in a page:
<Grid x:Name="LayoutRoot"
DataContext="{Binding Source={StaticResource MyContext}}"
d:DataContext="{d:DesignData SampleData/MyContextSampleData.xaml}">
The MyContext class has some properties that are references, not just simple data. One such property for that class is public MyReferenceType MyReferenceProperty.
I have built sample data for both MyContext and MyReferenceType.
Here is the MyReferenceTypeSampleData.xaml:
<data:MyReferenceType
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:data="clr-namespace:MyNamespace.Data;assembly=MyNamespace.Data"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
MyValueProperty0="True"
MyValueProperty1="123"
MyValueProperty2="abc"
/>
and MyContextSampleData.xaml is where I am stumped.
<data:MyContext
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:data="clr-namespace:MyNamespace.Data;assembly=MyNamespace.Data"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
MyReferenceProperty="{d:DesignData SampleData/MyReferenceTypeSampleData.xaml}"
/>
MyReferenceProperty="{d:DesignData SampleData/MyReferenceTypeSampleData.xaml}" is of course wrong. I am trying to do the equivalent of what this does for setting d:DataContext. I want the property to be set in the sample data to the sampledata xaml.
Is this possible and if not, what would be the common workaround. Surely this is a typical use case because mock data is rarely just value types. Anyone know how to handle this?

How to implement converter class in usercontrol

I want to make a converter class , I implemented it and i want to use it in another xaml class
So i write this code
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PoliceApp"
xmlns:common="using:PoliceApp.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Resources>
<local:TitleToImgConverter x:Key="BoolOrConverter"/>
</UserControl.Resources>
</UserControl>
It tells me that there is a missing attribute for user control
and my first code was
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PoliceApp"
xmlns:common="using:PoliceApp.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Resources>
<local:TitleToImgConverter x:Key="BoolOrConverter"/>
</UserControl.Resources>
And the error was "The name titletoimgconverter doesnt exist in the namespace using:policeApp"
This is normal (at least, I have never seen it otherwise) when you have just created a new converter and added it as a resource in your XAML code. XAML code often lags behind when something is added to the namespace.
The solution for this is to rebuild your entire project. The XAML should now be able to locate your converter, and the error should disappear.
Update
If your converter exists in some folder called Converter, you should use your first example, and replace xmlns:local="using:PoliceApp" with xmlns:local="clr-namespace:PoliceApp.Converter". If it just resides in your main folder, you can leave out the .Converter. Note that I've replaced the using: with clr-namespace:.

Categories