0

System.Windows.Data Error: 40 : BindingExpression path error: 'Length' property not found on 'object' ''ClockViewModel' (HashCode=13256970)'. BindingExpression:Path=Length; DataItem='ClockViewModel' (HashCode=13256970); target element is 'ClockUserControl' (Name=''); target property is 'Length' (type 'Double')

Binding не работает. Типа если вписать просто число без Binding , то все сработает. Я не знаю как это пофиксить.

Пожалуйста помогите решить проблему.

И ещо дайте рекомендации, как лучше б сделать , если это должно соответстывать патерну MVVM

MainWindow.xaml
OK

<Window x:Class="ClockUnit.View.MainWindow"
        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="clr-namespace:ClockUnit.View"
        xmlns:Clocker="clr-namespace:ClockUnit.View.UserControls"
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        xmlns:vm="clr-namespace:ClockUnit.ViewModel"
        >
    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>
&lt;Grid&gt;
    &lt;StackPanel Margin=&quot;0 20 0 0&quot;&gt;
        **&lt;Clocker:ClockUserControl Length=&quot;90&quot;/&gt;**
    &lt;/StackPanel&gt;



&lt;/Grid&gt;

</Window>

ERROR

<Window x:Class="ClockUnit.View.MainWindow"
        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="clr-namespace:ClockUnit.View"
        xmlns:Clocker="clr-namespace:ClockUnit.View.UserControls"
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        xmlns:vm="clr-namespace:ClockUnit.ViewModel"
        >
    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>
&lt;Grid&gt;
    &lt;StackPanel Margin=&quot;0 20 0 0&quot;&gt;
        **&lt;Clocker:ClockUserControl Length=&quot;{Binding Path=Length}&quot;/&gt;**
    &lt;/StackPanel&gt;



&lt;/Grid&gt;


</Window>

MainWindowViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace ClockUnit.ViewModel { public class MainWindowViewModel : ViewModelBase {

    public MainWindowViewModel()
    {

    }
    public double length = 50;
    public double Length
    {
        get =&gt; length;
        set { length = value; OnProperyChanged(nameof(length));}
    }

}

}

ClockUserControl.xaml.cs

<UserControl x:Class="ClockUnit.View.UserControls.ClockUserControl"
             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:local="clr-namespace:ClockUnit.View.UserControls"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             xmlns:vm="clr-namespace:ClockUnit.ViewModel" 
             >
&lt;UserControl.DataContext&gt;
    &lt;vm:ClockViewModel/&gt;
&lt;/UserControl.DataContext&gt;


&lt;Grid&gt;
    &lt;Canvas Width=&quot;200&quot; Height=&quot;200&quot; x:Name=&quot;ClockF&quot; Background=&quot;WhiteSmoke&quot;&gt;&lt;/Canvas&gt;
&lt;/Grid&gt;


</UserControl>

ClockUserControl.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using ClockUnit.ViewModel;
using ClockUnit.View.UserControls;
using System.ComponentModel;

namespace ClockUnit.View.UserControls { /// <summary> /// Логика взаимодействия для ClockUserControl.xaml /// </summary> public partial class ClockUserControl : UserControl {

    public readonly static DependencyProperty LengthKey = DependencyProperty.Register(&quot;Length&quot;, typeof(double), typeof(ClockUserControl), new PropertyMetadata(90.0));
    public double Length
    {
        get =&gt; (double)GetValue(LengthKey);
        set =&gt; SetValue(LengthKey, value);
    }


    public ClockUserControl()
    {
        this.DataContext = new ClockViewModel();
        InitializeComponent();
        StartTick();    
    }





    public SolidColorBrush ColorLine { get; set; } = new SolidColorBrush(Colors.Black);
    public int dx = 100;
    public int time;


    public void InitClock()
    {
        Ellipse ellipse = new Ellipse();
        ellipse.Width = 200;
        ellipse.Height = 200;
        ellipse.Stretch = Stretch.Fill;
        ellipse.Fill = Brushes.White;
        ellipse.Stroke = Brushes.Black;
        ellipse.StrokeThickness = 2;

        Ellipse point = new Ellipse();
        point.Width = 10;
        point.Height = 10;
        point.Fill = Brushes.Black;
        point.Margin = new Thickness(95, 95, 95, 95);

        ClockF.Children.Add(ellipse);
        ClockF.Children.Add(point);


        ClockF.MouseDown += ReturnColor;

    }
    public async void SecondLine()
    {

        double second = DateTime.Now.Second;


        double angle = (second / 59) * 6.28;

        Line line = new Line();

        line.X1 = dx;
        line.Y1 = dx;


        line.X2 = dx + Length * Math.Sin(angle);
        line.Y2 = dx - Length * Math.Cos(angle);

        line.Stroke = ColorLine;
        line.StrokeThickness = 3;



        line.MouseDown += MouseD;



        ClockF.Children.Add(line);

    }
    public async void Tick(object sender, EventArgs e)
    {
        this.Dispatcher.Invoke(() =&gt;
        {

            ClockF.Children.Clear();
            InitClock();
            SecondLine();

        }


        );

    }
    public void StartTick()
    {

        DispatcherTimer timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromMilliseconds(100);
        timer.Tick += Tick;
        timer.Start();

    }



    private void MouseD(object sender , MouseButtonEventArgs e)
    {
        ColorLine = Brushes.Red;
        time = e.Timestamp;
    }
    private void ReturnColor(object sender, MouseButtonEventArgs e)
    {
        if(e.Timestamp != time &amp;&amp; ColorLine != Brushes.Black)
        {
            ColorLine = Brushes.Black;
        }

    }



}

}

ClockViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClockUnit.ViewModel { public class ClockViewModel : ViewModelBase {

}

}

Я чуть переписал код, посмотрите его и пожалуйста дайте коментарии как его улучшить, изменение в MainWindow.xaml:

MainWindowViewModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace ClockUnit.ViewModel { public class MainWindowViewModel : ViewModelBase {

    public MainWindowViewModel()
    {
        SendMessage = new RelayCommand(Click);
    }
    public void Click()
    {
        Console.WriteLine(&quot;Click&quot;);
    }
    public ICommand SendMessage { get; set; }






    private double length = 30;
    public double Length
    {
        get =&gt; length; 
        set
        {
            length = value;
            OnProperyChanged(nameof(length));
        }
    }




}

}

ClockViewModel.cs

using ClockUnit.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ClockUnit.ViewModel { public class ClockViewModel: ViewModelBase { } }

MainWindow.xaml

<Window x:Class="ClockUnit.View.MainWindow"
        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="clr-namespace:ClockUnit.View"
        xmlns:Clocker="clr-namespace:ClockUnit.View.UserControls"
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        xmlns:vm="clr-namespace:ClockUnit.ViewModel"
        xmlns:convert ="clr-namespace:ClockUnit.View.UserControls.Convert"
        x:Name="MainWindowForm"
        >
    <Window.DataContext>
        <vm:MainWindowViewModel/>
    </Window.DataContext>
&lt;Grid&gt;
    &lt;StackPanel Margin=&quot;0 20 0 0&quot;&gt;
        **&lt;Clocker:ClockUserControl Length=&quot;{Binding Path=DataContext.Length, ElementName=MainWindowForm}&quot;/&gt;**
        &lt;TextBox Text=&quot;{Binding Length , UpdateSourceTrigger=PropertyChanged}&quot; Height=&quot;30&quot; Margin=&quot;0 20&quot; FontSize=&quot;22&quot; FontWeight=&quot;Bold&quot;/&gt;
    &lt;/StackPanel&gt;



&lt;/Grid&gt;


</Window>

ClockUserControl.xaml

<UserControl x:Class="ClockUnit.View.UserControls.ClockUserControl"
             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:local="clr-namespace:ClockUnit.View.UserControls"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             xmlns:vm ="clr-namespace:ClockUnit.ViewModel"
             >
&lt;UserControl.DataContext&gt;
    &lt;vm:ClockViewModel/&gt;
&lt;/UserControl.DataContext&gt;


&lt;Grid&gt;
    &lt;Canvas Width=&quot;200&quot; Height=&quot;200&quot; x:Name=&quot;ClockF&quot; Background=&quot;WhiteSmoke&quot; &gt;&lt;/Canvas&gt;
&lt;/Grid&gt;


</UserControl>

ClockUserControl.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using ClockUnit.ViewModel;
using ClockUnit.View.UserControls;
using System.ComponentModel;

namespace ClockUnit.View.UserControls { /// <summary> /// Логика взаимодействия для ClockUserControl.xaml /// </summary> public partial class ClockUserControl : UserControl {

    public readonly static DependencyProperty LengthKey = DependencyProperty.Register(&quot;Length&quot;, typeof(double), typeof(ClockUserControl), new PropertyMetadata(90.0));
    public double Length
    {
        get =&gt; (double)GetValue(LengthKey);
        set =&gt; SetValue(LengthKey, value);
    }


    public ClockUserControl()
    {
        InitializeComponent();
        this.DataContext = new ClockViewModel();
        StartTick();    
    }

    public SolidColorBrush ColorLine { get; set; } = new SolidColorBrush(Colors.Black);
    public int dx = 100;
    public int time;


    public void InitClock()
    {
        Ellipse ellipse = new Ellipse();
        ellipse.Width = 200;
        ellipse.Height = 200;
        ellipse.Stretch = Stretch.Fill;
        ellipse.Fill = Brushes.White;
        ellipse.Stroke = Brushes.Black;
        ellipse.StrokeThickness = 2;

        Ellipse point = new Ellipse();
        point.Width = 10;
        point.Height = 10;
        point.Fill = Brushes.Black;
        point.Margin = new Thickness(95, 95, 95, 95);

        ClockF.Children.Add(ellipse);
        ClockF.Children.Add(point);


        ClockF.MouseDown += ReturnColor;

    }
    public async void SecondLine()
    {

        double second = DateTime.Now.Second;


        double angle = (second / 59) * 6.28;

        Line line = new Line();

        line.X1 = dx;
        line.Y1 = dx;


        line.X2 = dx + Length * Math.Sin(angle);
        line.Y2 = dx - Length * Math.Cos(angle);

        line.Stroke = ColorLine;
        line.StrokeThickness = 3;



        line.MouseDown += MouseD;



        ClockF.Children.Add(line);

    }
    public async void Tick(object sender, EventArgs e)
    {
        this.Dispatcher.Invoke(() =&gt;
        {
            ClockF.Children.Clear();
            InitClock();
            SecondLine();

        }


        );

    }
    public void StartTick()
    {

        DispatcherTimer timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromMilliseconds(100);
        timer.Tick += Tick;
        timer.Start();

    }
    private void MouseD(object sender , MouseButtonEventArgs e)
    {
        ColorLine = Brushes.Red;
        time = e.Timestamp;
    }
    private void ReturnColor(object sender, MouseButtonEventArgs e)
    {
        if(e.Timestamp != time &amp;&amp; ColorLine != Brushes.Black)
        {
            ColorLine = Brushes.Black;
        }

    }



}

}

  • Не работает, потому что у вас нет Length в ClockViewModel. MainWindowViewModel, где вы определяет это свойство, с контролом не связано и он его не видит – demonplus Jul 17 '22 at 13:55
  • Добавьте еще в свой вопрос код ClockViewModel, пожалуйста – demonplus Jul 17 '22 at 13:56
  • Я добавил ClockViewModel – Maksym Shymchenko Jul 17 '22 at 14:07
  • Я чуть не понимаю просто как мне тогда совместить View(ClockUserControl) и ViewModel(ClockViewModel). Просто отрисовка происходит на Canvas , и данные для отрисовки в View(ClockUserControl). Очень сильно прошу переписать мой код в правильном формате, просто я уже добавил в ClockViewModel - Length , и далее не имею понятия как продолжать... – Maksym Shymchenko Jul 17 '22 at 14:19
  • Всякие <vm:MainWindowViewModel/> - плохо. А проблема ваша в том, что у вашего UserControl задан свой DataContext, в котором и ищется свойство, вам даже ошибка пишет "Нет свойства 'Length' в 'ClockViewModel". Что делать? Тут зависит от того, что это UserControl должен делать, за что отвечает. Если его задача бы просто контролом (как TextBox например), то у него вообще не должно быть VM слоя, он должен быть независимым, отдавая наружу только свои DP, а внутри должно быть что-то по типу {Binding Length, ElementName=uc}. – EvgeniyZ Jul 17 '22 at 15:31
  • Где uc - имя заданное самому UserControl через x:Name="uc". Если задача вашего контрола быть как "страница", то здесь вам надо идти от обратного, делать что-то по типу этого, где вы по типу задаете нужный вид. – EvgeniyZ Jul 17 '22 at 15:33

0 Answers0