我想将TextBlock的foreground属性绑定到ViewModel中的Property。
这不起作用:
修改
查看:
TextBlock
Text="{Binding Path=FullName, Mode=OneWay}"
Foreground="{Binding Path=ForegroundColor}"
Margin="0 5 3 5"
代码背后:
CustomerHeaderViewModel customerHeaderViewModel = new CustomerHeaderViewModel();
customerHeaderViewModel.LoadCustomers();
CustomerHeaderView.DataContext = customerHeaderViewModel;
查看型号:
private System.Windows.Media.Brush _foregroundColor;
_foregroundColor = System.Windows.Media.Brushes.DarkSeaGreen;
public System.Windows.Media.Brush ForegroundColor
{
get { return _foregroundColor; }
set { _foregroundColor = value;
OnPropertyChanged("ForegroundColor");
}
}
public CustomerHeaderViewModel()
{
ForegroundColor = System.Windows.Media.Brushes.Red;
}
所有其他属性(文本等)正确绑定。
我做错了什么?
答案 0 :(得分:21)
检查您的解决方案是否如此: 视图:
<Window x:Class="WpfApplication13.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:vm="clr-namespace:WpfApplication13"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<vm:MainVM/>
</Window.DataContext>
<Grid>
<TextBlock Text="{Binding Path=FullName, Mode=OneWay}"
Foreground="{Binding Path=ForegroundColor}"
Margin="0 5 3 5"/>
</Grid>
</Window>
视图模型:
public class MainVM : INotifyPropertyChanged
{
protected void OnPropertyChanged(string porpName)
{
var temp = PropertyChanged;
if (temp != null)
temp(this, new PropertyChangedEventArgs(porpName));
}
public event PropertyChangedEventHandler PropertyChanged;
private System.Windows.Media.Brush _foregroundColor = System.Windows.Media.Brushes.DarkSeaGreen;
public string FullName
{
get
{
return "Hello world";
}
}
public System.Windows.Media.Brush ForegroundColor
{
get { return _foregroundColor; }
set
{
_foregroundColor = value;
OnPropertyChanged("ForegroundColor");
}
}
}
并记住,如果你想在VM中为ForegroundColor设置新值,你可以这样做:
ForegroundColor = System.Windows.Media.Brushes.Red;
提出PropertyChangedEvent
根据您的问题的新信息,您可以尝试这个解决方案:
CustomerHeaderViewModel.cs
class CustomerHeaderViewModel : INotifyPropertyChanged
{
public ObservableCollection<Customer> Customers { get; set; }
public void LoadCustomers()
{
ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
//this is where you would actually call your service
customers.Add(new Customer { FirstName = "Jim", LastName = "Smith", NumberOfContracts = 23 });
customers.Add(new Customer { FirstName = "Jane", LastName = "Smith", NumberOfContracts = 22 });
customers.Add(new Customer { FirstName = "John", LastName = "Tester", NumberOfContracts = 33 });
customers.Add(new Customer { FirstName = "Robert", LastName = "Smith", NumberOfContracts = 2 });
customers.Add(new Customer { FirstName = "Hank", LastName = "Jobs", NumberOfContracts = 5 });
Customers = customers;
}
protected void OnPropertyChanged(string porpName)
{
var temp = PropertyChanged;
if (temp != null)
temp(this, new PropertyChangedEventArgs(porpName));
}
public event PropertyChangedEventHandler PropertyChanged;
private System.Windows.Media.Brush _foregroundColor = System.Windows.Media.Brushes.DarkSeaGreen;
public System.Windows.Media.Brush ForegroundColor
{
get { return _foregroundColor; }
set
{
_foregroundColor = value;
OnPropertyChanged("ForegroundColor");
}
}
}
CustomerHeaderView.xaml
<UserControl x:Class="TestMvvm444.Views.CustomerHeaderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="main">
<Grid>
<StackPanel HorizontalAlignment="Left">
<ItemsControl ItemsSource="{Binding Path=Customers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<TextBox
Text="{Binding Path=FirstName, Mode=TwoWay}"
Width="100"
Margin="3 5 3 5"/>
<TextBox
Text="{Binding Path=LastName, Mode=TwoWay}"
Width="100"
Margin="0 5 3 5"/>
<TextBlock
Text="{Binding Path=FullName, Mode=OneWay}"
Foreground="{Binding ElementName=main, Path=DataContext.ForegroundColor}"
Margin="0 5 3 5"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</UserControl>
在呈现的场景中,ForegroundColor属性驻留在CustomerHeaderViewModel.cs中,因此它对所有客户都是值。在CustomerHeaderView.xaml中,我为UserControl添加了x:Name,以便有可能引用此元素的DataContext。如果您不想对UserControl使用x:Name,可以尝试:
<TextBlock
Text="{Binding Path=FullName, Mode=OneWay}"
Foreground="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}}, Path=DataContext.ForegroundColor}"
Margin="0 5 3 5"/>
请记住,此控件的DataContext是在MainWindow.cs中设置的。
MainWindow.cs
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
CustomerHeaderViewModel customerHeaderViewModel = new CustomerHeaderViewModel();
customerHeaderViewModel.LoadCustomers();
CustomerHeaderView.DataContext = customerHeaderViewModel;
}
}
答案 1 :(得分:3)
将UI元素放入视图模型中不是一个好习惯。您的视图模型必须仅封装业务位置。
如果要更改UI中依赖于文本框值的任何内容的颜色,最好在XAML中使用数据触发器。
你可以这样做:
Viewmodel:
public class MainVm : INotifyPropertyChanged
{
protected void OnPropertyChanged(string porpName)
{
var temp = PropertyChanged;
if (temp != null)
temp(this, new PropertyChangedEventArgs(porpName));
}
public event PropertyChangedEventHandler PropertyChanged;
public string FullName
{
get { return "Hello world"; }
}
}
XAML(编辑使用颜色选择器,假设其控件的选定值被命名为“SelectedValue”并且它返回一个Brush对象)
<Grid>
<TextBlock Text="{Binding Path=FullName, Mode=OneWay}"
Margin="0 5 3 5" Foreground="{Binding ElementName=colorpicker, Path=SelectedValue}"/>
<ColorPicker x:Name="colorpicker"/>
</Grid>