有条件地将两个属性绑定到一个文本框
Conditional binding two properties to one Textbox
你好亲爱的程序员
我决定使用 C# 语言学习 MVVP 模式。这就是为什么我有一个问题要问你。我有一个非常简单的应用程序,它由 5 个文本框和一个按钮组成。它还没有完成。
我取得的成绩:
- 当我在第一个文本框(员工姓名)中写一些文本时,动态
搜索启动,所有匹配的记录都出现在列表中。
- 当我单击列表中的记录时,信息会出现在文本框中。
我想达到的目标:
- 当我在第一个文本框(员工姓名)中写一些文本时,动态
搜索启动,所有匹配的记录都出现在列表中。
- 当我单击列表中的记录时,信息会出现在文本框中。
- 当我编辑列表中的第一个文本框(员工姓名)时,员工姓名
不应该改变。 (仅在单击按钮后)。
观察:
我阅读了有关多绑定、转换器和 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
}
}
嗯,也许这个解决方案适合你?
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Collections.Generic;
using System.Linq;
namespace WpfApp1
{
public class EmployeeModel
{
public string Name { get; set; }
}
public class EmployeeViewModel : ViewModelBase
{
readonly EmployeeModel model;
string editName;
public EmployeeViewModel (EmployeeModel model)
{
this.model = model;
editName = Name;
SaveChanges = new RelayCommand (() => { Name = EditName; SaveChanges.RaiseCanExecuteChanged (); }, () => IsDirty);
}
public string Name
{
get => model.Name;
set
{
model.Name = value;
RaisePropertyChanged (nameof (Name));
}
}
public string EditName
{
get => editName;
set
{
editName = value;
RaisePropertyChanged (nameof (EditName));
SaveChanges.RaiseCanExecuteChanged ();
}
}
public bool IsDirty => editName != Name;
public RelayCommand SaveChanges { get; }
}
public class WindowViewModel
{
List<EmployeeModel> models = new List<EmployeeModel>
{
new EmployeeModel () { Name = "Janusz" },
new EmployeeModel () { Name = "Grażyna" },
new EmployeeModel () { Name = "John" },
};
public WindowViewModel ()
{
EmployeeViews = models.Select (x => new EmployeeViewModel (x)).ToList ();
}
public IEnumerable<EmployeeViewModel> EmployeeViews { get; }
public EmployeeViewModel SelectedEmployeeView { get; set; }
}
}
和xaml:
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:WindowViewModel/>
</Window.DataContext>
<Grid>
<ListBox ItemsSource="{Binding EmployeeViews}"
SelectedItem="{Binding SelectedEmployeeView}"
DisplayMemberPath="Name" Margin="26,26,565.6,0"
Height="274"
VerticalAlignment="Top"
Width="202"
/>
<Button Command="{Binding SelectedEmployeeView.SaveChanges}"
Content="Save"
HorizontalAlignment="Left"
Height="36"
Margin="245,81,0,0"
VerticalAlignment="Top"
Width="133"/>
<TextBox Text="{Binding SelectedEmployeeView.EditName, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left"
Height="23"
Margin="255,35,0,0"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="120"/>
</Grid>
</Window>
我已经自己解决了我的问题。我已将我的全部代码放在下面 :)
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 string dynamicSearch;
private int changedPathBinding;
public string EmployeeName
{
get
{
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 string DynamicSearch
{
get
{
if (SelectedEmployee == null)
{
EmployeeName = dynamicSearch;
}
return dynamicSearch;
}
set
{
dynamicSearch = value;
OnPropertyChanged("DynamicSearch");
}
}
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)
{
string[] SearchedCollection = ((string)parameter).Split(new char[] { ':' });
SelectedEmployee.EmployeeName = SearchedCollection[0];
//FilteredCollection.Filter = null;
SelectedEmployee = null;
//EmployeeName = null;
//EmployeeSalary = null;
}
bool CanSave
{
get
{
return SelectedEmployee != null;
}
}
}
}
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];
}
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();
return values;
}
}
public class ConverterButton : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string _employeeName = (string)values[0];
//MessageBox.Show("ButtonConverter: " + _employeeName);
return string.Format("{0}", _employeeName);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
MainWindows.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();
}
}
}
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" />
<local:ConverterButton x:Key="ConverterButton" />
</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="OneWay" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="DynamicSearch" 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}" >
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource ConverterButton}" UpdateSourceTrigger="Explicit" Mode="TwoWay">
<Binding ElementName="TextboxEmployeeName" Path="Text"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
</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
}
}
你好亲爱的程序员
我决定使用 C# 语言学习 MVVP 模式。这就是为什么我有一个问题要问你。我有一个非常简单的应用程序,它由 5 个文本框和一个按钮组成。它还没有完成。
我取得的成绩:
- 当我在第一个文本框(员工姓名)中写一些文本时,动态 搜索启动,所有匹配的记录都出现在列表中。
- 当我单击列表中的记录时,信息会出现在文本框中。
我想达到的目标:
- 当我在第一个文本框(员工姓名)中写一些文本时,动态 搜索启动,所有匹配的记录都出现在列表中。
- 当我单击列表中的记录时,信息会出现在文本框中。
- 当我编辑列表中的第一个文本框(员工姓名)时,员工姓名 不应该改变。 (仅在单击按钮后)。
观察:
我阅读了有关多绑定、转换器和 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
}
}
嗯,也许这个解决方案适合你?
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Collections.Generic;
using System.Linq;
namespace WpfApp1
{
public class EmployeeModel
{
public string Name { get; set; }
}
public class EmployeeViewModel : ViewModelBase
{
readonly EmployeeModel model;
string editName;
public EmployeeViewModel (EmployeeModel model)
{
this.model = model;
editName = Name;
SaveChanges = new RelayCommand (() => { Name = EditName; SaveChanges.RaiseCanExecuteChanged (); }, () => IsDirty);
}
public string Name
{
get => model.Name;
set
{
model.Name = value;
RaisePropertyChanged (nameof (Name));
}
}
public string EditName
{
get => editName;
set
{
editName = value;
RaisePropertyChanged (nameof (EditName));
SaveChanges.RaiseCanExecuteChanged ();
}
}
public bool IsDirty => editName != Name;
public RelayCommand SaveChanges { get; }
}
public class WindowViewModel
{
List<EmployeeModel> models = new List<EmployeeModel>
{
new EmployeeModel () { Name = "Janusz" },
new EmployeeModel () { Name = "Grażyna" },
new EmployeeModel () { Name = "John" },
};
public WindowViewModel ()
{
EmployeeViews = models.Select (x => new EmployeeViewModel (x)).ToList ();
}
public IEnumerable<EmployeeViewModel> EmployeeViews { get; }
public EmployeeViewModel SelectedEmployeeView { get; set; }
}
}
和xaml:
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:WindowViewModel/>
</Window.DataContext>
<Grid>
<ListBox ItemsSource="{Binding EmployeeViews}"
SelectedItem="{Binding SelectedEmployeeView}"
DisplayMemberPath="Name" Margin="26,26,565.6,0"
Height="274"
VerticalAlignment="Top"
Width="202"
/>
<Button Command="{Binding SelectedEmployeeView.SaveChanges}"
Content="Save"
HorizontalAlignment="Left"
Height="36"
Margin="245,81,0,0"
VerticalAlignment="Top"
Width="133"/>
<TextBox Text="{Binding SelectedEmployeeView.EditName, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left"
Height="23"
Margin="255,35,0,0"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="120"/>
</Grid>
</Window>
我已经自己解决了我的问题。我已将我的全部代码放在下面 :)
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 string dynamicSearch;
private int changedPathBinding;
public string EmployeeName
{
get
{
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 string DynamicSearch
{
get
{
if (SelectedEmployee == null)
{
EmployeeName = dynamicSearch;
}
return dynamicSearch;
}
set
{
dynamicSearch = value;
OnPropertyChanged("DynamicSearch");
}
}
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)
{
string[] SearchedCollection = ((string)parameter).Split(new char[] { ':' });
SelectedEmployee.EmployeeName = SearchedCollection[0];
//FilteredCollection.Filter = null;
SelectedEmployee = null;
//EmployeeName = null;
//EmployeeSalary = null;
}
bool CanSave
{
get
{
return SelectedEmployee != null;
}
}
}
}
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];
}
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();
return values;
}
}
public class ConverterButton : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string _employeeName = (string)values[0];
//MessageBox.Show("ButtonConverter: " + _employeeName);
return string.Format("{0}", _employeeName);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
MainWindows.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();
}
}
}
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" />
<local:ConverterButton x:Key="ConverterButton" />
</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="OneWay" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="DynamicSearch" 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}" >
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource ConverterButton}" UpdateSourceTrigger="Explicit" Mode="TwoWay">
<Binding ElementName="TextboxEmployeeName" Path="Text"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
</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
}
}