0

こんにちは親愛なるプログラマー

C# 言語を使用して MVVP パターンを学習することにしました。そこで、1 つ質問があります。5 つのテキスト ボックスと 1 つのボタンで構成される非常に単純なアプリケーションがあります。まだ終わっていません。

私が達成したこと:

  1. 最初のテキスト ボックス (従業員名) にテキストを入力すると、動的検索が起動し、一致したすべてのレコードがリストに表示されます。
  2. リスト内のレコードをクリックすると、テキスト ボックスに情報が表示されます。

私が達成したいこと:

  1. 最初のテキスト ボックス (従業員名) にテキストを入力すると、動的検索が起動し、一致したすべてのレコードがリストに表示されます。
  2. リスト内のレコードをクリックすると、テキスト ボックスに情報が表示されます。
  3. 最初のテキスト ボックス (従業員名) を編集すると、リスト内の従業員名は変更されません。(ボタンクリック後のみ)。

所見:

Multibinding、Converters、および UpdateSourcetrigger: Explicit と Propertychanged について読みました。テキストボックス TextboxEmployeeName をマルチバインドしようとしました。PropertyChangedを設定すると、動的検索は機能しますが、テキストボックスに書き込むとリスト内の従業員名が変更されますが、明示的に設定すると、リスト内の従業員名は変更されません(達成したいこと)が、動的検索は機能しません。

私の質問は: 条件に応じて適切な UpdateSourceTrigger を設定するにはどうすればよいですか?

If (Record is not selected) 
{
UpdateSourceTrigger = PropertyChanged
}
Else If (Record is selected)
{
UpdateSourceTrigger = Explicit
}

問題を解決するために良い方法をとったかどうかはわかりません。多分あなたはより良い解決策を知っていますか?私たちを手伝ってくれますか?以下にコード全体を配置しました。

Employee.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Windows;
using System.Collections.ObjectModel;
using System.Windows.Data;
using System.Windows.Threading;

namespace OneWayTwoWayBinding
{
    public class Employee : INotifyPropertyChanged
    {
        private string employeeName;
        private string employeeID;
        private int? employeeSalary;
        private string employeeDesigner;
        private string employeeEmailID;
        private Employee selectedEmployee;
        private ICollectionView filteredCollection;
        private Employee dynamicSearch;
        private int changedPathBinding;
        public string EmployeeName
        {
            get
            {
                //Application.Current.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(employeeName)));
                return employeeName;
            }
            set
            {
                employeeName = value;
                if (FilteredCollection != null)
                    FilteredCollection.Filter = x => (String.IsNullOrEmpty(employeeName) || ((Employee)x).EmployeeName.Contains(employeeName));
                OnPropertyChanged("EmployeeName");
            }
        }
        public string EmployeeID
        {
            get
            {
                return employeeID;
            }
            set
            {
                employeeID = value;
                OnPropertyChanged("EmployeeID");
            }
        }
        public int? EmployeeSalary
        {
            get
            {
                return employeeSalary;
            }
            set
            {
                employeeSalary = value;
                OnPropertyChanged("EmployeeSalary");
                if (FilteredCollection != null)
                    FilteredCollection.Filter = x => ((employeeSalary == null) || ((Employee)x).EmployeeSalary == employeeSalary);
            }
        }
        public string EmployeeDesigner
        {
            get
            {
                //Application.Current.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(employeeDesigner)));
                return employeeDesigner;
            }
            set
            {
                employeeDesigner = value;
                OnPropertyChanged("EmployeeDesigner");
                if (FilteredCollection != null)
                FilteredCollection.Filter = x => (String.IsNullOrEmpty(employeeDesigner) || ((Employee)x).EmployeeDesigner.Contains(employeeDesigner));
            }
        }
        public string EmployeeEmailID
        {
            get
            {
                return employeeEmailID;
            }
            set
            {
                employeeEmailID = value;
                OnPropertyChanged("EmployeeEmailID");
            }
        }
        public IList<Employee> EmployeeList
        {
            get; set;
        }

        public Employee SelectedEmployee
        {
            get
            {
                //Application.Current.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(selectedEmployee.SelectedEmployee.ToString())));
                return selectedEmployee;
            }
            set
            {
                selectedEmployee = value;
                OnPropertyChanged("SelectedEmployee");
            }
        }

        public Employee DynamicSearch
        {
            get
            {
                return dynamicSearch;
            }
            set
            {
                dynamicSearch = value;
                OnPropertyChanged("DynamicSearch");
                //FilteredCollection.Filter = x => (String.IsNullOrEmpty(dynamicSearch.EmployeeName) || ((Employee)x).EmployeeName.Contains(dynamicSearch.EmployeeName));
            }
        }
        public ICollectionView FilteredCollection
        {
            get
            {
                return filteredCollection;
            }
            set
            {
                filteredCollection = value;
                OnPropertyChanged("FilteredCollection");
            }
        }

        public int ChangedPathBinding
        {
            get
            {
                //Application.Current.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(changedPathBinding.ToString())));
                return changedPathBinding;
            }
            set
            {
                changedPathBinding = value;
                OnPropertyChanged("ChangedPathBinding");
                //SelectedEmployee.EmployeeName
            }
        }

        public ObservableCollection<Employee> Employees { get; private set; }

        public event PropertyChangedEventHandler PropertyChanged = null;
        virtual protected void OnPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

EmployeeViewModel.cs

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

namespace OneWayTwoWayBinding
{
    public class EmployeeViewModel : Employee
    {
        public EmployeeViewModel()
        {

            ObservableCollection<Employee> Employees = new ObservableCollection<Employee>()
            {
                new Employee{EmployeeName = "Adrian",EmployeeID = "1",EmployeeSalary = 15000,EmployeeDesigner = "SoftwareEngingeer12312", EmployeeEmailID = "drozd001@gmail423423.com"},
                new Employee{EmployeeName = "Bartek",EmployeeID = "2",EmployeeSalary = 15000,EmployeeDesigner = "SoftwareEngingeer",EmployeeEmailID = "drozd001@gmail.com"},
                new Employee{EmployeeName = "Czarek",EmployeeID = "3",EmployeeSalary = 30000,EmployeeDesigner = "SoftwareEngingeer",EmployeeEmailID = "drozd001@gmail.com"}
            };

            FilteredCollection = CollectionViewSource.GetDefaultView(Employees);

            //SelectedEmployee = new Employee {EmployeeName = string.Empty, EmployeeID = string.Empty, EmployeeSalary = string.Empty, EmployeeDesigner = string.Empty, EmployeeEmailID = string.Empty};

            //EmployeeDesigner = "SoftwareEngingeer12312";
            //EmployeeDesigner = "SoftwareEngingeer12312";
            //DynamicSearch.EmployeeName = "Czarek";
            //EmployeeSalary = 10;
            ChangedPathBinding = -1;
            SelectedEmployee = null;
        }

        RelayCommand _saveCommand;
        public ICommand SaveCommand
        {
            get
            {
                if (_saveCommand == null)
                {
                    _saveCommand = new RelayCommand((param) => this.Save(param),
                        param => this.CanSave);
                }
                return _saveCommand;
            }
        }

        public void Save(object parameter)
        {
            FilteredCollection.Filter = null;
            SelectedEmployee = null;
            EmployeeName = null;
            EmployeeSalary = null;
        }


        bool CanSave
        {
            get
            {
                return true;
            }
        }
    }

}

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
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;

namespace OneWayTwoWayBinding
{
    /// <summary>
    /// Logika interakcji dla klasy MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new EmployeeViewModel();
        }       
    }
}

Converters.cs

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;

namespace OneWayTwoWayBinding
{
    public class Converters : IValueConverter
    {
       public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
       {
            //value = 5; //ta liczba pojawi sie w textbox po uruchomieniu aplikacji
            return value;
       }
       public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
       {
        if (string.IsNullOrEmpty(value.ToString()))
            return null;
            //int var;
            //var = int.Parse(value.ToString());
            //var *= 2;
            //value = var;
        return value; //liczba wpisana w textbox z poziomu widoku aplikacji
       }
    }
    public class ConverterFiltering : IMultiValueConverter
    {
        public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value[0] == DependencyProperty.UnsetValue || value[1] == DependencyProperty.UnsetValue)
            {
                return value[0];
            }
            MessageBox.Show("Values[0]: " + value[0].ToString());
            //MessageBox.Show("Values[1]: " + value[1].ToString());
            return value[0];
        }
        public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
        {
            string[] values = new string[2];
            values[0] = value.ToString();
            values[1] = value.ToString();

            MessageBox.Show("Values[0]: " + values[0].ToString() + " Values[1]: " + values[1].ToString());
            return values;
        }
    }
}

MainWindow.xaml

<Window x:Class="OneWayTwoWayBinding.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:OneWayTwoWayBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <local:Converters x:Key="NullableValueConverter" />
        <local:ConverterFiltering x:Key="ConverterFiltering" />
    </Window.Resources>
    <Grid Margin="0,0,0,20">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ListView Name="EmployeeListView" HorizontalAlignment="Left" Height="160" Margin="0,259,0,0" VerticalAlignment="Top" Width="792" ItemsSource="{Binding FilteredCollection}" SelectedItem="{Binding SelectedEmployee, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedIndex="{Binding ChangedPathBinding}" >
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="EmployeeName" Width="150" DisplayMemberBinding="{Binding EmployeeName}" />
                    <GridViewColumn Header="EmployeeID" Width="150" DisplayMemberBinding="{Binding EmployeeID}" />
                    <GridViewColumn Header="EmployeeSalary" Width="150" DisplayMemberBinding="{Binding EmployeeSalary}" />
                    <GridViewColumn Header="EmployeeDesigner" Width="150" DisplayMemberBinding="{Binding EmployeeDesigner}" />
                    <GridViewColumn Header="EmployeeEmailID" Width="150" DisplayMemberBinding="{Binding EmployeeEmailID}" />
                </GridView>
            </ListView.View>
        </ListView>
        <Label Content="Employee Name" HorizontalAlignment="Left" Margin="15,52,0,0" VerticalAlignment="Top" Width="77" Height="23"/>

        <TextBox Name ="TextboxEmployeeName" HorizontalAlignment="Left" Height="23" Margin="97,52,0,0" VerticalAlignment="Top" Width="522" >
            <TextBox.Text>
                <MultiBinding Converter="{StaticResource ConverterFiltering}" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
                    <Binding Path="SelectedEmployee.EmployeeName" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" />
                    <Binding Path="EmployeeName"  Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
                </MultiBinding>
            </TextBox.Text>
        </TextBox>

        <Label Content="Label" HorizontalAlignment="Left" Margin="15,91,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
        <TextBox HorizontalAlignment="Left" Height="23" Margin="97,91,0,0"  Text="{Binding Path=SelectedEmployee.EmployeeID, Mode=TwoWay}" VerticalAlignment="Top" Width="522"/>
        <Label Content="Label" HorizontalAlignment="Left" Margin="15,131,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
        <TextBox HorizontalAlignment="Left" Height="23" Margin="97,131,0,0"  Text="{Binding EmployeeSalary, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource NullableValueConverter}}" VerticalAlignment="Top" Width="522"/>
        <Label Content="Label" HorizontalAlignment="Left" Margin="15,176,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
        <TextBox HorizontalAlignment="Left" Height="23" Margin="97,176,0,0" Text="{Binding EmployeeDesigner, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="522"/>
        <Label Content="Label" HorizontalAlignment="Left" Margin="15,221,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
        <TextBox HorizontalAlignment="Left" Height="23" Margin="97,221,0,0"  Text="{Binding SelectedEmployee.EmployeeEmailID, Mode=TwoWay}" VerticalAlignment="Top" Width="522"/>
        <Button Content="Button" HorizontalAlignment="Left" Margin="663,116,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="-0.017,0.456" Command="{Binding SaveCommand}"/>
    </Grid>
</Window>

RelayCommand.cs

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

namespace OneWayTwoWayBinding
{
    public class RelayCommand : ICommand
    {
        #region Fields 
        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;
        #endregion // Fields 
        #region Constructors 
        public RelayCommand(Action<object> execute) : this(execute, null) { }
        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute; _canExecute = canExecute;
        }
        #endregion // Constructors 
        #region ICommand Members 
        [DebuggerStepThrough]
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        public void Execute(object parameter) { _execute(parameter); }
        #endregion // ICommand Members 
    }
}
4

2 に答える 2