Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF:在使用MVVM时更改数据绑定_C#_Wpf_Xaml_Data Binding_Mvvm - Fatal编程技术网

C# WPF:在使用MVVM时更改数据绑定

C# WPF:在使用MVVM时更改数据绑定,c#,wpf,xaml,data-binding,mvvm,C#,Wpf,Xaml,Data Binding,Mvvm,下面是一个简单的例子,说明了我真正想做的事情,但我的问题是相同的 假设我有两个对象,男人和女人,它们都具有相同的属性(年龄、身高和体重),但它们是两个不同的对象。我不能改变这一点 现在假设我有一个WPF面板,使用MVVM原理制作,在文本框中显示某个男人的年龄。我使用Text=“{Binding Path=OnePerson.Age}”,其中OnePerson是viewmodel中定义的Man类型的对象 这很好,但我想要一个类似的页面来显示女性的信息。理想情况下,我希望使用与以前相同的视图和视图模

下面是一个简单的例子,说明了我真正想做的事情,但我的问题是相同的

假设我有两个对象,男人和女人,它们都具有相同的属性(年龄、身高和体重),但它们是两个不同的对象。我不能改变这一点

现在假设我有一个WPF面板,使用MVVM原理制作,在文本框中显示某个男人的年龄。我使用Text=“{Binding Path=OnePerson.Age}”,其中OnePerson是viewmodel中定义的Man类型的对象

这很好,但我想要一个类似的页面来显示女性的信息。理想情况下,我希望使用与以前相同的视图和视图模型。但这很棘手,因为数据绑定指向Man对象OnePerson。我可以通过编程方式更改数据绑定(如中所述),但只能从视图的代码隐藏中进行更改。我不允许这样做,因为我们使用的是MVVM模型

我想让一个人引用一个男人或女人对象,但我不知道这样做的好方法。它们是不同的类型,所以我不能只使用if语句指定一个男人或女人。我可以将一个人声明为一个对象而不是一个类型,但是我再也不能如此轻松地访问年龄、身高和体重属性了。或者我可以制作一个完全不同的视图模型,其中一个声明一个人为男性,另一个声明一个人为女性,并对他们两人使用相同的视图。我认为这应该行得通,但在一个视图中使用两个ViewModel似乎有点奇怪。添加我自己的Person类并将其与男性或女性进行转换可能会使整个viewmodel变得更加复杂,因为我开始添加功能,如添加新的男性/女性或编辑现有的男性/女性,到了这样的程度,我还可以复制粘贴“男人”视图和“视图”模型,只将“一个人”对象更改为“女人”

我的问题是,在这种情况下,是否有一种简洁的方法可以使用单个视图和Viewmodel来显示男性或女性的信息。或者我不应该费心为这些案例制作单独的页面


希望这足够清楚。

您是否考虑过基于接口对象制作对象。接口基本上创建了一个契约,声明从它派生的任何东西必须至少具有它声明的内容。。。派生控件可以有更多,但至少是您想要的。比如说

public interface IPersonProperties
{
   string PersonName { get; set; }
   int Age { get; set; }

   // if you want a function that is common between them too
   bool SomeCommonFunction(string whateverParms);

   etc...
}

public class Man : IPersonProperties
{
   // these required as to support the IPersonProperties
   public string PersonName { get; set; }
   public int Age { get; set; }

   public bool SomeCommonFunction(string whateverParms)
   {  doSomething;
      return true;
   }


   // you can still have other stuff specific to man class definition
   public string OtherManBasedProperty { get; set;}

   public void SomeManFunction()
   {  // do something specific for man here }
}

public class Woman : IPersonProperties
{
   // these required as to support the IPersonProperties
   public string PersonName { get; set; }
   public int Age { get; set; }

   public bool SomeCommonFunction(string whateverParms)
   {  doSomething;
      return false;
   }

   // you can still have other stuff specific to WOMAN class definition
   public string OtherWOMANBasedProperty { get; set;}

   public void SomeWomanFunction()
   {  // do something specific for man here }

}
然后,在MVVM中,可以公开的“对象”是IPersonProperties的对象,例如

public class YourMVVM
{
   public IPersonProperties BindToMe{ get; set }

   public YourMVVM()
   {
      BindToMe = new Man();
      // OR... BindToMe = new Woman();
   }
}
然后,在MVVM对象中创建对象的任何地方,都要这样做。您的绑定将是相同的,但可以是任意性别。如果它们之间通过接口有共同之处,您可以通过

if( BindToMe.SomeCommonFunction( "testing"))
   blah blah.
但是,如果在某些方法中你需要做一些基于性别的事情,你可以做

if( BindToMe is Man )
   ((Man)BindToMe).SomeManFunction();
else
   ((Woman)BindToMe).SomeWOMANFunction();

希望这能为您打开一些实现选择的大门。

您是否考虑过基于接口对象创建对象。接口基本上创建了一个契约,声明从它派生的任何东西必须至少具有它声明的内容。。。派生控件可以有更多,但至少是您想要的。比如说

public interface IPersonProperties
{
   string PersonName { get; set; }
   int Age { get; set; }

   // if you want a function that is common between them too
   bool SomeCommonFunction(string whateverParms);

   etc...
}

public class Man : IPersonProperties
{
   // these required as to support the IPersonProperties
   public string PersonName { get; set; }
   public int Age { get; set; }

   public bool SomeCommonFunction(string whateverParms)
   {  doSomething;
      return true;
   }


   // you can still have other stuff specific to man class definition
   public string OtherManBasedProperty { get; set;}

   public void SomeManFunction()
   {  // do something specific for man here }
}

public class Woman : IPersonProperties
{
   // these required as to support the IPersonProperties
   public string PersonName { get; set; }
   public int Age { get; set; }

   public bool SomeCommonFunction(string whateverParms)
   {  doSomething;
      return false;
   }

   // you can still have other stuff specific to WOMAN class definition
   public string OtherWOMANBasedProperty { get; set;}

   public void SomeWomanFunction()
   {  // do something specific for man here }

}
然后,在MVVM中,可以公开的“对象”是IPersonProperties的对象,例如

public class YourMVVM
{
   public IPersonProperties BindToMe{ get; set }

   public YourMVVM()
   {
      BindToMe = new Man();
      // OR... BindToMe = new Woman();
   }
}
然后,在MVVM对象中创建对象的任何地方,都要这样做。您的绑定将是相同的,但可以是任意性别。如果它们之间通过接口有共同之处,您可以通过

if( BindToMe.SomeCommonFunction( "testing"))
   blah blah.
但是,如果在某些方法中你需要做一些基于性别的事情,你可以做

if( BindToMe is Man )
   ((Man)BindToMe).SomeManFunction();
else
   ((Woman)BindToMe).SomeWOMANFunction();

希望这为您的实现选择打开了一些大门。

如果您只想针对您的年龄使用一个xaml控件,您可以这样做

ageusercontrol

  <TextBlock Text="{Binding Path=Age}" />

个人观点

   <local:AgeUserControl DataContext="{Binding Path=MyObjectTypePersonProperty} />

如果您只想针对您的年龄使用一个xaml控件,您可以这样做

ageusercontrol

  <TextBlock Text="{Binding Path=Age}" />

个人观点

   <local:AgeUserControl DataContext="{Binding Path=MyObjectTypePersonProperty} />

我认为与视图或绑定相比,
ViewModel
的问题更多。
视图
仅仅是
视图模型
的一个可视表示,听起来您的问题需要在
视图模型
中解决,而不是在
视图
中解决

WPF的绑定系统仅在绑定无效时发出警告,并且它不关心
DataContext
的数据类型。您问题中显示的绑定(
{binding OnePerson.Age}
)将正确计算,无论
OnePerson
Man
还是
Woman
对象,并将显示该对象上任何
Age
属性的值

因此,最好的解决方案是将
OnePerson
属性设置为
Man
Woman
类型。一个包含所有共享属性的接口将是理想的,因为这样代码就可以访问它的属性,而无需强制转换,并且您可以保留现有的所有绑定

IPerson OnePerson { get; set; }
如果无法使用共享接口,则可以使用
对象
,但是,在代码中引用其属性之前,您需要记住将
一个人
对象强制转换为
男人
女人

object OnePerson { get; set; }

...

if (((Man)OnePerson).Age < 0) ...
不过,您可能需要一些标志来标识哪个是填充的对象,并在更新对象的属性和确定视图的
DataContext

<Style x:Key="MyContentControlStyle">
    <Setter Property="Content" Value="{Binding SomeMan}" />
    <Style.Triggers>
        <DataTrigger Property="{Binding SelectedPersonType}" Value="Woman">
            <Setter Property="Content" Value="{Binding SomeWoman}" />
        </DataTrigger>
    </Style.Triggers>
</Style>
下面是一个使用标志确定
DataContext

<Style x:Key="MyContentControlStyle">
    <Setter Property="Content" Value="{Binding SomeMan}" />
    <Style.Triggers>
        <DataTrigger Property="{Binding SelectedPersonType}" Value="Woman">
            <Setter Property="Content" Value="{Binding SomeWoman}" />
        </DataTrigger>
    </Style.Triggers>
</Style>
总的来说,我建议您要么尝试使
OnePerson
成为两个对象共享的数据类型,要么为两个对象创建一个单独的
ViewModel
。听起来你们两个班都很相似,所以你们甚至可以