Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/25: Рейтинг темы: голосов - 25, средняя оценка - 5.00
1 / 1 / 1
Регистрация: 30.01.2013
Сообщений: 18

Не видно элемент XAML(View) в коде (ViewModel)

18.07.2015, 09:09. Показов 5287. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. Разбирал пример с MVVM отсюда http://howtowpf.ru/datagrid-mvvm/

Вот структура приложения Название: struct.JPG
Просмотров: 264

Размер: 22.2 Кб

Код XAML(View) мне необходимо элемент DataGrid Name="datagrid_view" увидеть в ViewModel.cs
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<Window x:Class="MyMVVM2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:MyMVVM2.ViewModel"
        
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:ViewModel/>
    </Window.DataContext>
    <Grid Background="LightGray">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="25"/>
            <RowDefinition Height="25"/>
            <RowDefinition Height="25"/>
        </Grid.RowDefinitions>
        <DataGrid x:Name="datagrid_view"  Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" ItemsSource="{Binding Path=Cars, Mode=TwoWay}" AutoGenerateColumns="false" SelectedIndex="{Binding SelectedIndex, Mode=TwoWay}"
                  SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Марка машины" Width="120" Binding="{Binding Path=Name, Mode=TwoWay}"/>
                <DataGridTextColumn Header="Стоимость машины" Width="120" Binding="{Binding Path=Price, Mode=TwoWay}"/>
            </DataGrid.Columns>
        </DataGrid>
        <Button Grid.Row="1" Grid.Column="2" Margin="2" Content="Исправить первую запись" Command="{Binding ClickCommandEditFirstObject}"/>
        <TextBlock Grid.Row="1" Grid.Column="0" Text="Марка машины" TextAlignment="Center" VerticalAlignment="Center"/>
        <TextBlock Grid.Row="1" Grid.Column="1" Text="Стоимость машины" TextAlignment="Center" VerticalAlignment="Center"/>
        <TextBox Grid.Row="2" Grid.Column="0" Margin="2" Text="{Binding Path=NewName, Mode=TwoWay}" />
        <TextBox Grid.Row="2" Grid.Column="1" Margin="2" Text="{Binding Path=NewPrice, Mode=TwoWay}" />
        <Button Grid.Row="2" Grid.Column="2" Margin="2" Content="Добавить запись"  Command="{Binding ClickCommand}"/>
        <Button Grid.Row="3" Grid.Column="2" Margin="2" Content="Edit запись"  Command="{Binding ClickCommandEditSelectedObject}"/>
    </Grid>
</Window>


Но у меня не получается!

Вот код С# (ViewModel.cs)
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
 
using MyMVVM2.Models;
using MyMVVM2;
 
namespace MyMVVM2.ViewModel
{
    
    class ViewModel
    {
        public ObservableCollection<Car> Cars { get; set; }
       
        public string NewName { get; set; }
        public int NewPrice { get; set; }
        public ICommand ClickCommand { get; set; }
        public ICommand ClickCommandEditFirstObject { get; set; }
        public ICommand ClickCommandEditSelectedObject { get; set; }
        public int SelectedIndex { get; set; }
        public Object SelectedItem { get; set; }
        
        public ViewModel()
        {
            Cars = new ObservableCollection<Car>()
            {
             new Car {Name = "Honda", Price= 30000},
             new Car {Name = "Ford", Price= 15000},
             new Car {Name = "Lada", Price= 5000}
             };
            ClickCommand = new RelayCommand(arg => ClickMethod());
            ClickCommandEditFirstObject = new RelayCommand(arg => ClickMethodEditFirstObject());
            ClickCommandEditSelectedObject = new RelayCommand(arg => ClickMethodEditSelectedObject());
            
        }
 
        private void ClickMethod()
        {
            Cars.Add(new Car() { Name = NewName, Price = NewPrice });
        }
        private void ClickMethodEditFirstObject()
        {
            Cars.First().Price *= 2; 
        }
        
        private void ClickMethodEditSelectedObject()
        {
          if (SelectedItem != null)   //так как SelectedItem это какой то объект , то необходимо проверить не пустой ли он 
            {
                Car tcaritem = SelectedItem as Car; //самый важный момент , тут мы получаем переменную типа CAR!
            //    MessageBox.Show(tcaritem.Name.ToString()); проверка
           
              for (int i = 0; i < Cars.Count; i++)
                     {
                         if (Cars[i].Name == tcaritem.Name)
                         { Cars[i].Price *= 2; }
                     } 
            }
        }
    
    }
}


Хотел добавить в метод "ClickMethodEditSelectedObject()" условие при котором будет проверятся не с пустой ли строкой мы пытаемся работать SelectedItem возвращает {NewItemPlaceholder} , да и вообще интересно почему не могу обратится к элементу XAML из кода класса?

Само изображение программы

Подскажите пожалуйста где косяк и как реализовать доступ к элементам во View из ViewModel.

P.S. Буду благодарен за любой комментарий.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
18.07.2015, 09:09
Ответы с готовыми решениями:

Доступ к полям MainWindow.xaml.cs из ViewModel
Здравствуйте пробую обычным способом получить доступ к полям MainWindow.xaml.cs или к public class Test ValueViewModel() //...

Binding View к ViewModel
Есть Модель, это компания, с кучей public свойств c OnPropertyChanged(Адрес, телефон, email и т.д.) Есть View, с кучей полей для свойств...

Определить View по типу ViewModel
собственно такой вопрос, у меня есть вм с сервисом, который что-то делает, в данном случае не имеет значения что: public class...

7
burning1ife
 Аватар для kenny69
1466 / 1287 / 294
Регистрация: 21.09.2008
Сообщений: 3,438
Записей в блоге: 9
18.07.2015, 16:44
Нажатия кнопки связывать через Command Binding. http://habrahabr.ru/post/196960/
Цитата Сообщение от code hunter Посмотреть сообщение
мне необходимо элемент DataGrid Name="datagrid_view" увидеть в ViewModel.cs
Вы не понимаете принципа MVVM.

ViewModel и View совершенно разные классы, они не должны знать о существовании друг друга.
Если вы хотите получить доступ к DataGrid, то вы можете сделать это во View.xml.cs
1
1 / 1 / 1
Регистрация: 30.01.2013
Сообщений: 18
18.07.2015, 20:42  [ТС]
Спасибо большое за ответ!
Но как тогда решить проблему с тем что когда прибинденное свойство SelectedItem
таблицы DataGrid к переменной SelectedItem типа Object возвращает в себе {NewItemPlaceholder} в классе ViewModel
XML
1
 SelectedItem="{Binding SelectedItem, Mode=TwoWay}
C#
1
 public Object SelectedItem { get; set; }
и приложение падает при проверке условия в методе ClickMethodEditSelectedObject ,
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
 private void ClickMethodEditSelectedObject()
        {
          if (SelectedItem != null)   //так как SelectedItem это какой то объект , то необходимо проверить не пустой ли он 
            {
                Car tcaritem = SelectedItem as Car; //самый важный момент , тут мы получаем переменную типа CAR!
          
              for (int i = 0; i < Cars.Count; i++)
                     {
                         if (Cars[i].Name == tcaritem.Name)
                         { Cars[i].Price *= 2; }
                     } 
            }
        }
т.е. условие оно как раз проходит (потому что SelectedItem что то получил - например если выбрана пустая новая строка он получит NewItemPlaceholder)
и при присвоении содержимого в переменную типа car (это единичная запись коллекции) выпадает ошибка
C#
1
  Car tcaritem = SelectedItem as Car;

Собственно проблему решил добавлением условия проверки принадлежности объекта к классу SelectedItem is Car
C#
1
2
3
4
********
            if ((SelectedItem != null)&&( SelectedItem is Car))   //так как SelectedItem это какой то объект , то необходимо проверить не пустой ли он и является объектом Car
            {
                Car tcaritem = SelectedItem as Car;

Но осталась неясность , возможно ли получить доступ к к элементу XAML(View) из кода класса ViewModel?
Очень хотелось бы знать, если нужно то вот проект MyMVVM2.zip
0
burning1ife
 Аватар для kenny69
1466 / 1287 / 294
Регистрация: 21.09.2008
Сообщений: 3,438
Записей в блоге: 9
18.07.2015, 21:49
Цитата Сообщение от code hunter Посмотреть сообщение
возможно ли получить доступ к к элементу XAML(View) из кода класса ViewModel?
Все выполняется через Binding. Так можно решить практически любую задачу. Вы просто скажите для какой цели, возможно это можно сделать соблюдая паттерн MVVM.
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
19.07.2015, 02:03
code hunter, View знает о ViewModel, а ViewModel знает о Model
View -> ViewModel -> Model

Передавать во ViewModel ссылку на любой из элементов View неправильно. Да и смысл тогда использовать MVVM, если это делать?

Добавлено через 1 минуту
Внутри View можно получать доступ к ViewModel и ей манипулировать прямо в коде View, но не передавать во ViewModel ссылки на любой элемент из View и на само View.

Добавлено через 4 минуты
микрооптимизация:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void ClickMethodEditSelectedObject()
{
    Car tcaritem = SelectedItem as Car; 
 
    if (tcaritem != null)
    {
        for (int i = 0; i < Cars.Count; i++)
        {
            if (Cars[i].Name == tcaritem.Name)
            {
                Cars[i].Price *= 2;
            }
        }
    }
}
1
1 / 1 / 1
Регистрация: 30.01.2013
Сообщений: 18
19.07.2015, 09:41  [ТС]
Цитата Сообщение от kenny69 Посмотреть сообщение
Все выполняется через Binding. Так можно решить практически любую задачу. Вы просто скажите для какой цели, возможно это можно сделать соблюдая паттерн MVVM.
Я понимаю что в рамках MVVM так не делается , но тут уже берет верх любопытство.

Возможно ли все таки при такой конструкции получить доступ к элементу XAML из другого класса ,может кому то уже приходилось так делать.


Просто у меня мало опыта в программировании под WPF , и хотелось бы знать как можно больше тонкостей.
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
19.07.2015, 10:11
Лучший ответ Сообщение было отмечено code hunter как решение

Решение

code hunter, кнопка, которую нужно скопировать к себе и закинуть в Grid
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
xmlns:local1="clr-namespace:MyMVVM2"
 
<Button Grid.Row="3"
         Grid.Column="1"
         Width="75"
         Height="22"
         Margin="39,2,0,0"
         HorizontalAlignment="Left"
         VerticalAlignment="Top"
         Command="{Binding TestCommand}"
         CommandParameter="{Binding Mode=OneWay,
                                    RelativeSource={RelativeSource FindAncestor,
                                                                  AncestorType={x:Type local1:MainWindow}}}"
         Content="Button" />
Добавить во ViewModel
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public RelayCommand TestCommand
{
    get
    {
        return _testCommand ?? (_testCommand = new RelayCommand(
            (obj) =>
            {
                var mainView = obj as MainWindow;
                if (mainView == null)
                    return;
                mainView.datagrid_view.Background = Brushes.Tomato;
            }));
    }
}
1
1 / 1 / 1
Регистрация: 30.01.2013
Сообщений: 18
19.07.2015, 18:42  [ТС]
Спасибо за ответ!

Это в принципе то что нужно, теперь буду разбираться дальше, там много еще нового нужно узнать. )
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.07.2015, 18:42
Помогаю со студенческими работами здесь

Привязка команды во View к другой ViewModel
Есть View. У нее есть ViewModel. Нужно при нажатии кнопки вызвать команду из другой ViewModel. Как это сделать? Спасибо.

Подписка из функции ViewModel на Completed из View
У меня есть вот такой сториборд в триггере &lt;Grid.Triggers&gt; &lt;EventTrigger RoutedEvent=&quot;Button.Click&quot;...

DataTemplates относится к View или ViewModel
по немного изучаю mvvm вот такой вопрос есть класс public class DataTemplates : DataTemplateSelector { public...

Как правильно связать ViewModel с View?
Как правильно связать ViewModel с View? 1. ViewModel должна быть полем-членом View? 2. ViewModel отдельно от View, но присваивается...

Паттерн MVVM. Взаимодействие ViewModel с View
Пишу приложение, используя паттерн mvvm. Есть солюшн, и в нем три проекта. %appname%View, %appname%ViewModel, %appname%Model. Ну и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru