3

I use C#, MVVM, WPF and Resharper.

When using the following code:

    public bool CombiBanksSelected
    {
        get { return _selectedBanksType == ESelectedBanksType.CombiBanks; }
        set
        {

I get a warning of Resharper: Make set accessor private.

When making the set method private, I get an InvalidOperationException: A TwoWay or OneWayToSource binding cannot work on the read-only property ''CombiBanksSelected'' of type ''PcgTools.ViewModels.PcgViewModel.'

Of course I can suppress it by adding:

    public bool CombiBanksSelected
    {
        get { return _selectedBanksType == ESelectedBanksType.CombiBanks; }
// ReSharper disable MemberCanBePrivate.Global
        set
// ReSharper restore MemberCanBePrivate.Global
        {

But this is not looking nice and not feeling good. Is there a better alternative or solution for this problem?

According to the answer I should change the XAML code. Mine is:

<UserControl x:Class="PcgTools.PcgWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ViewModels="clr-namespace:PcgTools.ViewModels" Height="Auto" Width="Auto" 
    Loaded="Window_Loaded">

<Grid>
  ...
    <RadioButton Content="_Programs" Height="16" HorizontalAlignment="Left" Margin="12,12,0,0" Name="radioButtonPrograms" VerticalAlignment="Top" 
                 IsChecked="{Binding Path=ProgramBanksSelected}" IsEnabled="{Binding Path=ProgramsEnabled}"/>
    <RadioButton Content="_Combis" Height="16" HorizontalAlignment="Left" Margin="85,12,0,0" Name="radioButtonCombis" VerticalAlignment="Top" 
                 IsChecked="{Binding Path=CombiBanksSelected}"  IsEnabled="{Binding Path=CombisEnabled}"/>

I have the Resharper problem for both (and more) properties binded to IsChecked (ProgramBanksSelected and CombiBanksSelected in the code above).

In the answer is shown that I should use a DataTemplate, but I still can't figure out how exactly (with not using MVVM light's Locator).

How should I use the data context/template?

Michel Keijzers
  • 15,025
  • 28
  • 93
  • 119
  • Well, perhaps Resharper is just wrong in this case? – Vlad Mar 03 '12 at 19:40
  • Yes but it happens on every occasion which are about 20 locations and I don''t like to spoil my code by adding all the disable remarks. – Michel Keijzers Mar 03 '12 at 19:44
  • 1
    @MichelKeijzers: could be that property `CombiBlankSelected` is actually used only as like `readonly` one, isn't it? – Tigran Mar 03 '12 at 19:50
  • 1
    Right, if a member is *only* ever called via Reflection -- your code never sets CombiBanksSelected at all -- it's generally speaking useful to warn about that and require you to specify that this is an exception to an otherwise useful rule. –  Mar 03 '12 at 19:52
  • 2
    You can create custom settings for resharper to ignore errors and warnings. – Ash Burlaczenko Mar 03 '12 at 19:58
  • 1
    If the property is set only via reflection, there is no need if `two-way` binding, just use one way wirh privatw `set` and problem is resolved. – Tigran Mar 03 '12 at 20:17
  • Can we see the xaml where you bind to this property? – Phil Mar 03 '12 at 20:30
  • 1
    @Tigran Data binding uses reflection internally, and as far as I am aware you have no control of the `BindingFlags` that get used. –  Mar 03 '12 at 21:03
  • 1
    @hvd:I'm aware of that, but as much as I understood, OP uses reflection to set the value, for some reason. And you can specify in `XAML` the *direction* of the binding. – Tigran Mar 03 '12 at 21:58
  • 1
    @Tigran Ah, I misunderstood you... My understanding is that the point is to have a two-way binding, which internally relies on reflection to call the property setter. –  Mar 03 '12 at 22:00
  • 1
    I didn't mean to imply you had to use MVVM light, it's just what I like to use. In your case is you specify then VS and R# can do their stuff. If you want design time data (which is good)then add ', IsDesignTimeCreatable=true'. – Phil Mar 04 '12 at 09:02

3 Answers3

9

Resharper doesn't have enough information to deduce the setter is being used. For example:

This code:

public partial class Page2
{
    public Page2()
    {
        InitializeComponent();

        DataContext = new List<ViewModel>
                          {
                              new ViewModel()
                          };
    }
}

public class ViewModel : ViewModelBase
{
    private bool _combiBanksSelected;
    public bool CombiBanksSelected
    {
        get { return _combiBanksSelected; }
        set
        {
            Set(()=>CombiBanksSelected, ref _combiBanksSelected, value);
        }
    }
}

with this Xaml:

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="Template" >
            <CheckBox IsChecked="{Binding CombiBanksSelected}"/>
        </DataTemplate>
    </Grid.Resources>
    <ListBox ItemsSource="{Binding}" ItemTemplate="{StaticResource Template}" />
</Grid>

will show the setter as not being used (when SWA is turned on).

However if you change the Xaml (adding DataType="{x:Type Samples:ViewModel}") to:

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="Template" DataType="{x:Type Samples:ViewModel}">
            <CheckBox IsChecked="{Binding CombiBanksSelected}"/>
        </DataTemplate>
    </Grid.Resources>
    <ListBox ItemsSource="{Binding}" ItemTemplate="{StaticResource Template}" />
</Grid>

R# now has enough information and doesn't show the warning.

Of course there are other ways of giving R# and VS Intellisense more hints about the types you're using. Examples are:

Using MVVM Light's view locator:

<UserControl ...
    DataContext="{Binding AViewModel, Source={StaticResource Locator}}" />

Using d:DataContext. I recommend looking a this MSDN walkthrough

<UserControl ...
    d:DataContext="{d:DesignInstance AViewModel, IsDesignTimeCreatable=true}"

Explicitly setting the DataContext

<UserControl.Resources>
    <AViewModel x:Key="theModel/>
</UserControl.Resources>

<Grid DataContext="{StaticResource theModel}"> ...

etc...

Any of these methods allow R# and VS to infer the use of types and provide intellisense.

Phil
  • 42,255
  • 9
  • 100
  • 100
  • Can you show me how I should use the DataTemplate according to your solution? – Michel Keijzers Mar 03 '12 at 22:27
  • 1
    I've added some more examples. I would need to see your xaml to know exactly what you need to do. If you're using an ItemsControl you should be able to move the ItemTemplate into a DataTemplate and provide a type. – Phil Mar 03 '12 at 22:35
  • I'm not using MVVM Light, however I think I can use some parts of your answer, but I'm trying to incorporate it myself first. – Michel Keijzers Mar 03 '12 at 22:38
  • I can't figure it out so I have added some code. I hope you (or someone else) can help me with connecting the DataContext to the radio buttons. Thanks in advance. – Michel Keijzers Mar 03 '12 at 23:07
  • I used the UsedImplicitly tag which I think is even more clear than your solution (although yours is maybe more 'theorethically correct''. – Michel Keijzers Mar 04 '12 at 00:20
3

In addition to Phil's excellent suggestions, you can also use the UsedImplicitlyAttribute. You can use Nuget to do add the dll for you

enter image description here

And then R# will itself offer to decorate the setter with the attribute:

public bool CombiBanksSelected
{
    get { return _selectedBanksType == ESelectedBanksType.CombiBanks; }
    [UsedImplicitly] set
    {

I find it less noisy than a comment, and well suited to a ViewModel where it's understood that data bindings are typically unknown to R#. (sometimes I actually prefer a comment to remind me why I wanted R# to shut up, but not in this case).

Cheers,
Berryl

Berryl
  • 12,471
  • 22
  • 98
  • 182
  • Thanks, this was exactly what I was looking for. Btw, in the link http://www.jetbrains.com/resharper/webhelp/Code_Analysis__External_Annotations.html is shown how to use the above. – Michel Keijzers Mar 04 '12 at 00:19
  • 1
    That's fine if you basically want R# to be quiet and go away, but then you're losing any benefit of R#. If you give R# enough info (in the xaml) you get all the R# goodness in your xaml - rename refactoring, intellisense, goto declaration etc. – Phil Mar 04 '12 at 08:57
  • @Phil Yes you are right in that ... I will add it to my future 'things to do' because your solution is the best (but not the easiest for now). – Michel Keijzers Mar 04 '12 at 12:38
2

resharper is a great tool... but it can be wrong occasionally.

You should not annotate your source code with comments to please resharper. Or any other tool for that matter. The tool is wrong, so dont fix the code, fix the tool.

So tell resharper to ignore it. Right click on the icon in the leftmargin and tell it to ignore this kind of problem going forward, or put it in the hint category. I like that option because you can still acess the solution, if it applies, but r# does not show it in the graphical summary on the right.

  • Yes I did that for now, however I like the message that a property so the code looks a bit messy with all those disabling/enabling of R# warnings. – Michel Keijzers Mar 03 '12 at 23:57