我正在使用MVVM设计一些复杂的UserControl。 UserControls的datacontext处理所有逻辑,并将UserControl交互的结果提供给控件的使用者。
我面临的问题是看起来像内部不适用于绑定,如果我尝试绑定到非公共绑定的源属性不起作用。如果我必须打开(amek public)我的VM顶部的所有源属性能够绑定它们,那么我打开UserControl和消费者的内部:
有什么想法吗?
提前致谢。
编辑:嗯,看this看来,来源必须始终公开,对。但后来我仍然面临着公开内幕的问题。任何解决方案?
示例:
您创建一个通用的UserControl。控件应该是一个黑盒子,它接受最终用户提供的查询,以某种方式向他显示查询返回的行,并让UserControl使用者获取所选值。该控件使用显示行的Combobox实现。
UserControl在UserControl.xaml中,并且有一个UserControlVM.cs文件,其中包含UserControl的ViewModel。
ViewModel包含要执行的查询,查询返回的项目列表以及所选项目。项目列表和所选项目是公共的,可以绑定到UserControl。
使用者在其窗口内使用UserControl的一个实例,在其窗口视图模型中使用UserControlVM的一个实例。我面临的问题是,当用户只能访问所选项目时,最终用户可以访问查询返回的项目列表。
答案 0 :(得分:0)
Binding
类的所有属性定位都需要公开
这是一种可能的替代解决方案:
您的DataContext
(如果是ViewModel
)可能会实施INotifyPropertyChanged
。
如果是这样,那么当您在DataContext
上设置ViewModel
(UserControl
)时,只需订阅PropertyChanged
事件处理程序,然后在代码隐藏中编写逻辑来操作您的控制取决于更改的数据。
答案 1 :(得分:0)
作为类的实现细节的数据不应该是公开的,但在我看来,您甚至不应该想要绑定到这种类型的数据。绑定到视图的数据应该是视图模型的公共属性和命令。请注意,视图模型定义了您的UI 。
用户界面不允许更改的公共属性应该只实现getter而不是setter。只能在特定条件下更改的公共属性应在setter中强制执行这些条件。视图模型应该提供并容纳所有UI逻辑(属性和命令)。
您还应该将视图模型包装在测试所有这些内容的单元测试中。
根据评论反馈进行更新:
class MyViewModel : ViewModelBase
{
private bool _showSomething;
public bool ShowSomething
{
get { return _showSomething; }
set
{
_showSomething = value;
RaisePropertyChanged("ShowSomething");
RaisePropertyChanged("TheThing");
}
}
public Something TheThing
{
get
{
if(_showSomething) { return _theThing; }
return _theOtherThing;
}
}
private Something _theThing;
private Something _theOtherThing;
}
编辑*:以下内容可能更接近基于评论的内容。
public interface IQueryControl
{
string Query { get; set; } //view passes query in
ReadOnlyCollection<string> QueryResultDescriptions { get; } //bind to combo items
string SelectedQueryDescription { get; set; } //bind to combo selection
object SelectedItem { get; } //resulting object
}
public class UserControlVM : ViewModelBase, IQueryControl
{
private string _query;
private ObservableCollection<object> _queryResults;
private ReadOnlyCollection<string> _externalResults;
private object _selectedResult;
public string Query
{
get { return _query; }
set
{
_query = value;
RaisePropertyChanged("Query");
UpdateQueryResults();
}
}
private void UpdateQueryResults()
{
//Do query which allocates / updates _queryResults;
_externalResults = new ReadOnlyCollection<string>((from entry in _queryResults select entry.ToString()).ToList<string>());
RaisePropertyChanged("QueryResultDescriptions");
}
public ReadOnlyCollection<string> QueryResultDescriptions
{
get { return _externalResults; }
}
public string SelectedQueryDescription
{
get { return _selectedResult.ToString(); }
set
{
SelectResult(value);
}
}
private void SelectResult(string value)
{
Dictionary<string, object> lookup = _queryResults.ToDictionary<object, string>((result) => { return result.ToString(); });
if (lookup.ContainsKey(value))
{
_selectedResult = lookup[value];
RaisePropertyChanged("SelectedQueryDescription");
RaisePropertyChanged("SelectedItem");
}
else
{
//throw something
}
}
public object SelectedItem
{
get { return _selectedResult; }
}
}
答案 2 :(得分:0)
我找到了一个解决方案(但是如果您的ViewModel需要构造函数参数,我会推进您的工作无效。)