全部 -
我正在尝试根据Observable集合中的当前项(也在VM中)设置VM中的公共属性。基本上 - 我想根据我的行将shadecolor设置为蓝色或粉红色(参见下面的示例代码)。另请参阅最终结果的图像。
有人可以建议 - 我怎么能做到这一点 - 我真的遇到了这个问题
请参阅以下示例代码:
Model.cs
public class Model
{
public Employee empdetails { get; set; }
}
public class Employee
{
public string fname { get; set; }
public string lname { get; set; }
public Enum gender { get; set; }
}
public enum gender
{
Male,
Female
}
ViewModel.cs
public class ViewModel
{
public ObservableCollection<Model> employees {get; set;}
public myCommand NextCommand { get; set; }
private Color _shadecolor;
public Color shadecolor
{
get
{
return _shadecolor;
}
set
{
_shadecolor = value;
}
}
public ViewModel()
{
employees = new ObservableCollection<Model>()
{
#region Populating Emp 1
new Model()
{
empdetails = new Employee()
{
fname = "John",
lname = "Smith",
gender = gender.Male
}
},
#endregion
#region Populating Emp 2
new Model()
{
empdetails = new Employee()
{
fname = "Robert",
lname = "Ally",
gender = gender.Female
}
},
#endregion
};
NextCommand = new myCommand(myNextCommandExecute, myCanNextCommandExecute);
}
private void myNextCommandExecute(object parameter)
{
}
private bool myCanNextCommandExecute(object parameter)
{
return true;
}
}
View.xaml
<Window x:Class="WpfApplication1.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="View" Height="500" Width="500" WindowStyle="None" AllowsTransparency="True" Background="Transparent">
<Border VerticalAlignment="Top" HorizontalAlignment="Left" BorderBrush="Silver" BorderThickness="2" CornerRadius="15">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.511,0.957">
<GradientStop Color="LightGray" Offset="0.55" />
<GradientStop Color="{Binding shadecolor}" Offset="1.3" />
</LinearGradientBrush>
</Border.Background>
<Grid Width="300" Height="300" Margin="3">
<StackPanel VerticalAlignment="Top" >
<TextBlock Text="{Binding Path=employees/empdetails.fname}" />
<Button Command="{Binding NextCommand}" Content="Next" Width="100"></Button>
</StackPanel>
</Grid>
</Border>
</Window>
答案 0 :(得分:1)
我相信你想要的是绑定SelectedItem = {Binding SelectedItem},其中Selected项也在视图模型上,公开为可观察的属性。
public Model SelectedItem
{
...
}
我不完全确定你在这里想要实现的是什么,因为你的XAML中没有任何东西来自Selector,因此这里没有选定项目的概念。
答案 1 :(得分:1)
为什么不使用ValueConverter?
<GradientStop Color="{Binding Path=gender, Converter={StaticResource GenderToColorConverter}" Offset="1.3" />
然后在你的价值转换器里面:
If value == Gender.Male return blue;
return pink;
从技术上讲,我认为你会返回一个画笔,但不要引用我。
以下是一些示例代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel(GetTestEmployees());
}
static IEnumerable<Employee> GetTestEmployees()
{
return new[]
{
new Employee()
{
FirstName = "Tom",
LastName = "Selleck",
Gender = Gender.Male
},
new Employee()
{
FirstName = "Pat",
LastName = "Sajak",
Gender = Gender.Male,
},
new Employee()
{
FirstName = "Mae",
LastName = "West",
Gender = Gender.Female
}
};
}
}
public class ViewModel : INotifyPropertyChanged
{
public ViewModel(IEnumerable<Employee> employees)
{
_employees = new ObservableCollection<Employee>(employees);
SelectedEmployee = employees.First();
}
ObservableCollection<Employee> _employees;
public ObservableCollection<Employee> Employees
{
get { return _employees; }
}
Employee _selectedEmployee;
public Employee SelectedEmployee
{
get { return _selectedEmployee; }
set
{
_selectedEmployee = value;
RaisePropertyChangedEvent("SelectedEmployee");
}
}
public void Next()
{
var curr = Employees.IndexOf(_selectedEmployee);
if (curr == -1) throw new ArgumentOutOfRangeException();
var next = (curr + 1) % Employees.Count;
SelectedEmployee = Employees[next];
}
ICommand _nextCommand;
public ICommand NextCommand
{
get
{
if (_nextCommand == null)
_nextCommand = new NextCommand(this);
return _nextCommand;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChangedEvent(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public class NextCommand : ICommand
{
ViewModel _viewModel;
public NextCommand(ViewModel viewModel)
{
_viewModel = viewModel;
}
public bool CanExecute(object parameter)
{
//throw new NotImplementedException();
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
//throw new NotImplementedException();
_viewModel.Next();
}
}
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Gender Gender { get; set; }
}
public enum Gender
{
Male,
Female
}
public class GenderToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var gender = (Gender)value;
if (gender == Gender.Male)
{
return Colors.Blue;
}
return Colors.Pink;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
这是相应的标记:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<loc:GenderToColorConverter x:Key="GenderToColorConverter"/>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Employees}"
SelectedItem="{Binding SelectedEmployee}">
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<Grid>
<ContentControl DataContext="{TemplateBinding SelectedItem}">
<StackPanel >
<StackPanel.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.511,0.957">
<GradientStop Color="LightGray" Offset="0.55" />
<GradientStop Color="{Binding Path=Gender, Converter={StaticResource GenderToColorConverter}}" Offset="1.3" />
</LinearGradientBrush>
</StackPanel.Background>
<TextBox Text="{Binding FirstName}"/>
<TextBox Text="{Binding LastName}"/>
</StackPanel>
</ContentControl>
</Grid>
</ControlTemplate>
</ListBox.Template>
</ListBox>
<Button VerticalAlignment="Bottom" HorizontalAlignment="Center" Content="Next" Command="{Binding NextCommand}"/>
</Grid>
</Window>
答案 2 :(得分:0)
我能够使用Firoso提到的方法实现这个(完全可行的)解决方案(利用Josh的最佳实践,将UI逻辑保留在VM之外)。
发布完整的代码段/图片以造福他人。
模型
public class Model : CommonBase
{
public Employee empdetails { get; set; }
}
public class Employee : CommonBase
{
private string _fname;
public string fname
{
get
{
return _fname;
}
set
{
_fname = value;
OnPropertyChanged("fname");
}
}
public string lname { get; set; }
private Enum _gender;
public Enum gender
{
get
{
return _gender;
}
set
{
_gender = value;
OnPropertyChanged("gender");
}
}
}
public enum gender
{
Male,
Female
}
视图模型
public class ViewModel
{
public Model employees { get; set; }
public myCommand NextCommand { get; set; }
public ViewModel()
{
employees = new Model()
{
empdetails = new Employee()
{
fname = "John",
lname = "Doe",
gender = gender.Male
}
};
NextCommand = new myCommand(myNextCommandExecute, myCanNextCommandExecute);
}
private void myNextCommandExecute(object parameter)
{
employees.empdetails.fname = "Ally";
employees.empdetails.lname = "Smith";
employees.empdetails.gender = gender.Female;
}
private bool myCanNextCommandExecute(object parameter)
{
return true;
}
}
查看
<Window x:Class="WpfApplication1.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:WpfApplication1"
Title="View" Height="500" Width="500" WindowStyle="None" AllowsTransparency="True" Background="Transparent">
<Window.Resources>
<loc:GendertoColorConverter x:Key="GendertoColorConverter"/>
</Window.Resources>
<Border VerticalAlignment="Top" HorizontalAlignment="Left" BorderBrush="Silver" BorderThickness="2" CornerRadius="15">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.511,0.957">
<GradientStop Color="LightGray" Offset="0.55" />
<GradientStop Color="{Binding Path=employees.empdetails.gender, Converter={StaticResource GendertoColorConverter}}" Offset="1.3" />
</LinearGradientBrush>
</Border.Background>
<Grid Width="300" Height="300" Margin="3">
<StackPanel VerticalAlignment="Top" >
<TextBlock Text="{Binding Path=employees.empdetails.fname}" />
<Button Command="{Binding NextCommand}" Content="Next" Width="100"></Button>
</StackPanel>
</Grid>
</Border>