我知道这里有一些类似的话题,但我无法从他们那里得到任何答案。 我必须在Windows Phone 7应用程序中将网格背景更新为图像或颜色。我使用我的值转换器,它工作正常,但我必须重新加载集合,以便更新颜色或图像。
<Grid Background="{Binding Converter={StaticResource ImageConverter}}" Width="125" Height="125" Margin="6">
转换器接收对象然后从中获取颜色和图像,这里是转换器
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
People myC = value as People;
string myImage = myC.Image;
object result = myC.TileColor;
if (myImage != null)
{
BitmapImage bi = new BitmapImage();
bi.CreateOptions = BitmapCreateOptions.BackgroundCreation;
ImageBrush imageBrush = new ImageBrush();
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists(myImage))
{
using (
IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile(myImage, FileMode.Open,
FileAccess.Read))
{
bi.SetSource(fileStream);
imageBrush.ImageSource = bi;
}
}
else
{
return result;
}
}
return imageBrush;
}
else
{
return result;
}
}
我需要以某种方式更新/刷新网格标记或值转换器,以便它可以显示最新的更改!
编辑
添加了更多代码
模特:
[Table]
public class People : INotifyPropertyChanged, INotifyPropertyChanging
{
private int _peopleId;
[Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
public int PeopleId
{
get { return _peopleId; }
set
{
if (_peopleId != value)
{
NotifyPropertyChanging("PeopleId");
_peopleId = value;
NotifyPropertyChanged("PeopleId");
}
}
}
private string _peopleName;
[Column]
public string PeopleName
{
get { return _peopleName; }
set
{
if (_peopleName != value)
{
NotifyPropertyChanging("PeopleName");
_peopleName = value;
NotifyPropertyChanged("PeopleName");
}
}
}
private string _tileColor;
[Column]
public string TileColor
{
get { return _tileColor; }
set
{
if (_tileColor != value)
{
NotifyPropertyChanging("TileColor");
_tileColor = value;
NotifyPropertyChanged("TileColor");
}
}
}
private string _image;
[Column]
public string Image
{
get { return _image; }
set
{
if (_image != value)
{
NotifyPropertyChanging("Image");
_image = value;
NotifyPropertyChanged("Image");
}
}
}
[Column]
internal int _groupId;
private EntityRef<Groups> _group;
[Association(Storage = "_group", ThisKey = "_groupId", OtherKey = "Id", IsForeignKey = true)]
public Groups Group
{
get { return _group.Entity; }
set
{
NotifyPropertyChanging("Group");
_group.Entity = value;
if (value != null)
{
_groupId = value.Id;
}
NotifyPropertyChanging("Group");
}
}
[Column(IsVersion = true)]
private Binary _version;
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
#region INotifyPropertyChanging Members
public event PropertyChangingEventHandler PropertyChanging;
private void NotifyPropertyChanging(string propertyName)
{
if (PropertyChanging != null)
{
PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
}
}
#endregion
}
ViewModel:
public class PeopleViewModel : INotifyPropertyChanged
{
private PeopleDataContext PeopleDB;
// Class constructor, create the data context object.
public PeopleViewModel(string PeopleDBConnectionString)
{
PeopleDB = new PeopleDataContext(PeopleDBConnectionString);
}
private ObservableCollection<People> _allPeople;
public ObservableCollection<People> AllPeople
{
get { return _allPeople; }
set
{
_allPeople = value;
NotifyPropertyChanged("AllPeople");
}
}
public ObservableCollection<People> LoadPeople(int gid)
{
var PeopleInDB = from People in PeopleDB.People
where People._groupId == gid
select People;
AllPeople = new ObservableCollection<People>(PeopleInDB);
return AllPeople;
}
public void updatePeople(int cid, string cname, string image, string tilecol)
{
People getc = PeopleDB.People.Single(c => c.PeopleId == cid);
getc.PeopleName = cname;
getc.Image = image;
getc.TileColor = tilecol;
PeopleDB.SubmitChanges();
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
申请页面
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox Margin="0,8,0,0" x:Name="Peoplelist" HorizontalAlignment="Center" BorderThickness="4" ItemsSource="{Binding AllPeople}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="{Binding Converter={StaticResource ImageConverter}}" Width="125" Height="125" Margin="6">
<TextBlock Name="name" Text="{Binding PeopleName}" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
应用程序页面代码
public partial class PeopleList : PhoneApplicationPage
{
private int gid;
private bool firstRun;
public PeopleList()
{
InitializeComponent();
firstRun = true;
this.DataContext = App.ViewModel;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
gid = int.Parse(NavigationContext.QueryString["Id"]);
if (firstRun)
{
App.ViewModel.LoadPeople(gid);
firstRun = false;
}
}
}
答案 0 :(得分:2)
Background="{Binding Converter={StaticResource ImageConverter}}"
建议您直接绑定到People
项(这是刷新时的问题)。
所以,你应该重新安排一下。改为使用其他“更高”数据上下文的a property
。
如何重新排列内容:
1)您的'模型'(来自db的实体)应该与您的视图模型不同。为了避免详细说明,它解决了很多问题 - 例如就像你一样。 People
getter / setter通常不会以这种方式覆盖(EF经常使用反射来处理w /实体等)。
因此,让PeopleVM(对于单个人或PersonViewModel
) - 在那里复制东西 - 并在那里制作INotify - 留下人们只是一个纯粹的实体/ poco w /自动获取/设置。
2)PeopleViewModel
相同 - 它与Db过于紧密(这些也是设计指南)。
你不应该重复使用DbContext - 不要保存它 - 它是一个“一次性”对象(并在其中缓存) - 所以使用using()
来处理和加载/更新点播。
3)使用PersonViewModel 替换主VM中的人员。当您从db加载时,首先将其泵入PersonVM - 当您以相反的方式保存时。这对于MVVM来说是一个棘手的问题,你经常需要复制/复制 - 你可以使用一些工具来自动化或只是复制ctor-s或其他东西。
您的ObservableCollection<People> AllPeople
变为ObservableCollection<PersonViewModel> AllPeople
4)XAML - 您的绑定AllPeople,PeopleName是相同的 - 但现在指向视图模型(和名称到VM名称)。
但是你应该将grid
绑定到PersonViewModel
(旧人)以外的其他内容 - 因为在收集内部时很难“刷新”。
a)创建一个新的单一属性,如ImageAndTileColor
- 并确保在/当两个属性中的任何一个更改时更新/通知。
b)另一个选择是使用MultiBinding
- 并绑定2,3个属性 - 一个是你拥有的整个PersonViewModel
以及另外两个属性 - 例如......
<Grid ...>
<Grid.Background>
<MultiBinding Converter="{StaticResource ImageConverter}" Mode="OneWay">
<MultiBinding.Bindings>
<Binding Path="Image" />
<Binding Path="TileColor" />
<Binding Path="" />
</MultiBinding.Bindings>
</MultiBinding>
</Grid.Background>
<TextBlock Name="name" Text="{Binding PeopleName}" ... />
</Grid>
这样你就可以在3次更改中强制修改 - 并且你仍然拥有完整的人物(实际上你只需要使用两个,因为你需要的只有Image和TileColor) 。
5)将您的转换器更改为IMultiValue ...并读取发送的多个值。
这就是全部:)
短篇版本:
这是proper way
并确定可以工作(这取决于您更新Person属性的方式/时间等) - 但您可以先尝试short version
- 只需执行multi-binding
部分即可人们建模 - 并希望它能够发挥作用。如果不是,你必须做以上所有。
Windows Phone 7:
由于没有MultiBinding
...
- 使用the workaround - 它应该非常相似,
- 或者使用上面的(a)
- 绑定网格到{Binding ImageAndTileColor, Converter...}
。创建新属性(如果您希望在实体/模型中也可以这样做 - 只需将其标记为[NotMapped()]
),这将是一个“复合”属性。
<小时/> http://www.thejoyofcode.com/MultiBinding_for_Silverlight_3.aspx
答案 1 :(得分:0)
我明白了(感谢NSGaga)。我把他的帖子作为答案,以下是我做的事情
首先,我需要让转换器接收PeopleId而不是对象本身
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int cid = (int)value;
People myC = App.ViewModel.getPerson(cid);
string myImage = myC.Image;
object result = myC.TileColor;
if (myImage != null)
{
BitmapImage bi = new BitmapImage();
bi.CreateOptions = BitmapCreateOptions.BackgroundCreation;
ImageBrush imageBrush = new ImageBrush();
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists(myImage))
{
using (
IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile(myImage, FileMode.Open,
FileAccess.Read))
{
bi.SetSource(fileStream);
imageBrush.ImageSource = bi;
}
}
else
{
return result;
}
}
return imageBrush;
}
else
{
return result;
}
}
然后,每当我像这样更新Image或TileColor时,我只需要添加调用NotifyPropertyChanged("PeopleId")
private string _tileColor;
[Column]
public string TileColor
{
get { return _tileColor; }
set
{
if (_tileColor != value)
{
NotifyPropertyChanging("TileColor");
_tileColor = value;
NotifyPropertyChanged("TileColor");
NotifyPropertyChanged("PeopleId");
}
}
}
private string _image;
[Column]
public string Image
{
get { return _image; }
set
{
if (_image != value)
{
NotifyPropertyChanging("Image");
_image = value;
NotifyPropertyChanged("Image");
NotifyPropertyChanged("PeopleId");
}
}
}
这会强制值转换器刷新:)