** [解决] **这是我在这里提出的第一个问题,所以有些错误可以通过。
在我的WPF应用程序中,我想以“双向模式”将所有控件绑定到特殊对象实例BuildingManagementSystem
中的相应属性,我想将其设置为Window DataContext。
但没有任何作用(数据不显示)。绑定它的正确方法是什么?
这是我的代码:
public partial class MainWindow : Window
{
BuildingManagementSystem bms { get; set; }
public MainWindow()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Window1_Loaded);
}
void Window1_Loaded(object sender, RoutedEventArgs e)
{
bms = new BuildingManagementSystem();
this.DataContext = bms;
}
public class BuildingManagementSystem
{
public string Name { get; set; }
public readonly FireAlarmSystem FireAlarmSystem;
public BuildingManagementSystem()
{
FireAlarmSystem = new FireAlarmSystem();
}
}
class FireAlarmSystem
{
private int alarmSmokeRate, currentSmokeRate;
public List<PowerConsumer> Devices { get; set; }
public int CurrentSmokeRate
{
get { return currentSmokeRate; }
set { SetField(ref currentSmokeRate, value, () => CurrentSmokeRate); }
}
public FireAlarmSystem()
{
Devices = new List<PowerConsumer>();
}
}
class PowerConsumer
{
public string Name { get; set; }
public double Power { get; set; }
public int Priority { get; set; }
public bool Enabled { get; set; }
}
XAML:
<DataGrid Name="FireAlarmGrid" HorizontalAlignment="Left" Margin="10,51,0,0" CanUserAddRows="True"
CanUserDeleteRows="True" VerticalAlignment="Top" AutoGenerateColumns="False" ItemsSource="{Binding FireAlarmSystem.Devices}" >
<DataGrid.RowValidationRules>
<local:FireValidationRule ValidationStep="UpdatedValue"/>
</DataGrid.RowValidationRules>
<DataGrid.Columns>
<DataGridCheckBoxColumn Header="Enabled" Binding="{Binding Enabled}"></DataGridCheckBoxColumn>
<DataGridTextColumn Header="Name" Binding="{Binding Name,ValidatesOnExceptions=True }" >
</DataGridTextColumn>
<DataGridTextColumn Header="Power" Binding="{Binding Power}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<TextBox Name="tbCurrentSmokeRate" Text="{Binding Path=FireAlarmSystem.CurrentSmokeRate, Mode=TwoWay}" VerticalAlignment="Top" Width="70"/>
答案 0 :(得分:1)
我个人喜欢创建viewmodel的静态实例,如下所示:
<Window.Resources>
<ViewModels:MainWindowVM x:Key="VM"></ViewModels:MainWindowVM>
当我这样做时,绑定很容易,因为专业页面在VS中找到了你的属性。
<StackPanel Grid.Column="0" Margin="5,5,5,0"
DataContext="{Binding Source={StaticResource VM}}">
但请记住,您需要添加命名空间
xmlns:ViewModels="clr-namespace:MyWPF.ViewModels"
xmlns:Views="clr-namespace:MyWPF.Views"
这允许属性绑定如下:
<Views:UcTitle x:Name="XTitle" ></Views:UcTitle>
<Views:UcLegendTitle x:Name="XLegendTitle"/>
<Views:UcSeriesTitle x:Name="XSeriesTitle" />
<Views:UcSeriesTypes x:Name="XSeriesTypes"/>
而且您不必在...中键入任何名称 在您的情况下,您没有使用ViewModel,但您正在正确设置数据上下文。所以这只能是没有要显示的数据或不正确的属性绑定。记住这个工作你需要三件事1)DataContext 2)Vales和3)按名称正确绑定...这是第三个在刚刚开始使用伟大的WPF绑定系统时惹恼了很多人。
答案 1 :(得分:0)
让MVVM正常工作......
您需要更新View Model以实现INotifyPropertyChanged,让wpf知道您的属性已更改
使用Observable集合而不是列表,ObservableCollections具有让Datagrid listview,列表框知道集合中的项目已更改的连线
将字段更改为属性,以便WPF可以看到它......
<DataGrid Name="FireAlarmGrid" HorizontalAlignment="Left" Margin="10,51,0,0" CanUserAddRows="True"
CanUserDeleteRows="True" VerticalAlignment="Top" AutoGenerateColumns="False" ItemsSource="{Binding FireAlarmSystem.Devices}" >
<DataGrid.RowValidationRules>
<local:FireValidationRule ValidationStep="UpdatedValue"/>
</DataGrid.RowValidationRules>
<DataGrid.Columns>
<DataGridCheckBoxColumn Header="Enabled" Binding="{Binding Enabled,Mode=TwoWay}"></DataGridCheckBoxColumn>
<DataGridTextColumn Header="Name" Binding="{Binding Name,ValidatesOnExceptions=True,Mode=TwoWay }" >
</DataGridTextColumn>
<DataGridTextColumn Header="Power" Binding="{Binding Power,Mode=TwoWay}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<TextBox Name="tbCurrentSmokeRate" Text="{Binding Path=FireAlarmSystem.CurrentSmokeRate, Mode=TwoWay}" VerticalAlignment="Top" Width="70"/>
public class BuildingManagementSystem : INotifyPropertyChanged
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
if (_Name != value)
{
_Name = value;
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
private FireAlarmSystem _fireAlarmSystem;
public FireAlarmSystem FireAlarmSystem { get { return _fireAlarmSystem; } }
public BuildingManagementSystem()
{
_fireAlarmSystem = new FireAlarmSystem();
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged = delegate { };
#endregion
}
public class FireAlarmSystem : INotifyPropertyChanged
{
private int alarmSmokeRate, currentSmokeRate;
public ObservableCollection<PowerConsumer> Devices { get; set; }
public int CurrentSmokeRate
{
get { return currentSmokeRate; }
set
{
//SetField(ref currentSmokeRate, value, () => CurrentSmokeRate);
PropertyChanged(this, new PropertyChangedEventArgs("CurrentSmokeRate"));
}
}
public FireAlarmSystem()
{
Devices = new ObservableCollection<PowerConsumer>();
//Create some test data...
Devices.Add(new PowerConsumer() { Name = "One", Enabled = true, Power = 100, Priority = 1 });
Devices.Add(new PowerConsumer() { Name = "two", Enabled = false, Power = 101, Priority = 2 });
Devices.Add(new PowerConsumer() { Name = "three", Enabled = false, Power = 103, Priority = 3 });
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged = delegate { };
#endregion
}
public class PowerConsumer
{
public string Name { get; set; }
public double Power { get; set; }
public int Priority { get; set; }
public bool Enabled { get; set; }
}
答案 2 :(得分:0)
这里有几个错误
取代BuildingManagementSystem bms {get;组;写下面的代码:
BuildingManagementSystem bms = new BuildingManagementSystem();
答案 3 :(得分:0)
感谢所有人,我发现了一个错误,它将FireAlarmSystem
定义为readonly
,它被称为属性。
2 Stuart Smith,你是INotifyPropertyChanged
的右边,但我有一个抽象的类 - 祖先BuildingSystem
,它实现了这个接口。我忘记发帖了。