我有一个MainWindow.xaml,MainwindowViewModel.cs,HaemogramReport.xaml和HaemogramReport.xaml.cs。我的项目中也有其他文件,但问题出在上面提到的四个文件中。 我在这里发布最小代码,以便其他人可以解决问题。
现在在HaemogramReport.xaml中,我声明了一些控件,如Grid
,TextBox
,TextBlock
,Rectangle
,Border
,ContentControl
等。
例如HaemogramReport.xaml
如下:
<Page.DataContext>
<vm:MainWindowViewModel />
</Page.DataContext>
<Grid DataContext="{Binding Source={StaticResource Settings}}" PreviewMouseDown="Object_Selection" x:Name="Root">
<Border Style="{StaticResource BorderStyle}" x:Name="HaemogramTestBorder"
Grid.Row="{Binding Default.HaemogramTestGridRow}" Grid.Column="{Binding Default.HaemogramTestGridColumn}"
Grid.RowSpan="{Binding Default.HaemogramTestGridRowSpan}" Grid.ColumnSpan="{Binding Default.HaemogramTestGridColumnSpan}">
<Grid>
<Rectangle Fill="Transparent" x:Name="HaemogramTestRectangle"/>
<TextBlock x:Name="HaemogramTestTextBlock"
Text="{Binding Default.HaemogramTestText}" Visibility="{Binding Default.HaemogramTestVisibility}"
Background="{Binding Default.HaemogramTestBackground, Converter={StaticResource colorToSolidColorBrushConverter}}"
Foreground="{Binding Default.HaemogramTestForeground, Converter={StaticResource colorToSolidColorBrushConverter}}"
FontFamily="{Binding Default.HaemogramTestFontFamily, Converter={StaticResource stringToFontFamilyConverter}}"
FontSize="{Binding Default.HaemogramTestFontSize}"
FontWeight="{Binding Default.HaemogramTestFontWeight}" FontStyle="{Binding Default.HaemogramTestFontStyle}"
HorizontalAlignment="{Binding Default.HaemogramTestHorizontalAlignment}"
VerticalAlignment="{Binding Default.HaemogramTestVerticalAlignment}"
Margin="{Binding Default.HaemogramTestMargin}" />
</Grid>
</Border>
</Grid>
当我点击上述声明元素中的任何元素时,会引发名为Root
的网格的mousedown事件。
该事件处理程序位于HaemogramReport.xmal.cs
中。这是:
private void Object_Selection(object sender, MouseButtonEventArgs e)
{
var mouseWasDownOn = e.Source as FrameworkElement;
if (mouseWasDownOn != null)
{
foreach (Border border in FindVisualChildren<Border>(Root))
{
border.BorderBrush = Brushes.Transparent;
}
if (!(mouseWasDownOn is Border))
{
FindParent<Border>(mouseWasDownOn).BorderBrush = Brushes.Orange;
}
MainWindowViewModel mwvm = new MainWindowViewModel();
mwvm.SelectedObj = mouseWasDownOn;
}
}
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
//get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
T parent = parentObject as T;
if (parent != null)
return parent;
else
return FindParent<T>(parentObject);
}
在名为Root
的Grid的mouseDown处理程序中,我说mwvm.SelectedObj = mouseWasDownOn;
SelectedObj是FrameworkElement类型的属性,它在MainwindowViewModel.cs
中声明如下:
private FrameworkElement selectedObj;
public FrameworkElement SelectedObj
{
get
{
return selectedObj;
}
set
{
selectedObj = value;
OnPropertyChanged("SelectedObj");
}
}
现在在我的MainWindow中,我有一个网格和一个textBox。有问题的绑定在这里声明。 xaml看起来像:
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
<Grid DataContext="{Binding SelectedObj, UpdateSourceTrigger=PropertyChanged}">
<TextBox Text="{Binding Text, UpdateSourceTrigger=PropertyChanged, TargetNullValue='null', FallbackValue='Error'}"/>
</Grid>
使用上面的代码时,我总是在TextBox上面得到Text Error
。
我第一次认为这可能是绑定错误,所以我更改了MainWindowViewModel.cs
如下:
public class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
SelectedObj = txt;
}
TextBlock txt = new TextBlock()
{
Text = "123"
};
private FrameworkElement selectedObj;
public FrameworkElement SelectedObj
{
get
{
return selectedObj;
}
set
{
selectedObj = value;
OnPropertyChanged("SelectedObj");
}
}
}
在我运行项目后进行上述更改后,我可以在文本框中看到123
但是当我点击任何元素时,文本框中的文字不会改变。
现在的问题是,如果它是一个绑定错误,那么为什么在第二个示例中我在文本框中得到123
而在第一个示例中我得到Error
- 回退值。
如果它不是绑定错误那么上面代码中的问题是什么?
更新
当我调试时,我发现永远不会调用get
的{{1}}部分。但我不知道为什么?
更新 - Reed Copsey
这是我的新课程:
SelectedObj
我用它像:
public class DesignMethods
{
public static void FindCurrentlyClickedElement(DependencyObject Root, MouseButtonEventArgs e, MainWindowViewModel vm)
{
var mouseWasDownOn = e.OriginalSource as FrameworkElement;
if (mouseWasDownOn != null)
{
foreach (Border border in FindVisualChildren<Border>(Root))
{
border.BorderBrush = Brushes.Transparent;
}
if (!(mouseWasDownOn is Border))
{
FindParent<Border>(mouseWasDownOn).BorderBrush = Brushes.Orange;
}
vm.SelectedObj = mouseWasDownOn;
}
}
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
//get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
//we've reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we're looking for
T parent = parentObject as T;
if (parent != null)
return parent;
else
return FindParent<T>(parentObject);
}
}
答案 0 :(得分:2)
问题是你正在创建一个ViewModel的新实例,而不是使用现有的实例:
// This is not the same instance you're binding to!
// MainWindowViewModel mwvm = new MainWindowViewModel();
// Get the existing one instead
var mwvm = this.DataContext as MainWindowViewModel;
mwvm.SelectedObj = mouseWasDownOn;
请注意,我可能不会在这里使用术语“ViewModel”。您正在做的事情不是典型的MVVM场景,因为您将DataContext实例紧密耦合到View中,并且两个方向都发生耦合,这与MVVM的正常目标完全相反。
编辑:
您可能还需要更新SelectedObj
的绑定。我建议尝试将XAML设置为:
<Grid>
<TextBox Text="{Binding SelectedObj.Text, UpdateSourceTrigger=PropertyChanged, TargetNullValue='null', FallbackValue='Error'}"/>
</Grid>
答案 1 :(得分:0)
尝试使用OriginalSource代替来源:
var mouseWasDownOn = e.OriginalSource as FrameworkElement;
因为处理复合控件时Source属性可以是包含OriginalSource对象的父级(在您的情况下是网格)。
答案 2 :(得分:0)
我认为您的错误可能是FrameworkElement没有Text属性http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement(v=vs.110).aspx
编辑:尝试更新Text上的绑定
{Binding SelectedObj.Text}
答案 3 :(得分:0)
我认为您的错误可能是您使用的是“常用”属性而不是DependencyProperties。
正如您在Microsoft说明中看到的那样
“当您定义自己的属性并希望它们支持许多属性时 Windows Presentation Foundation(WPF)功能的各个方面, 包括样式,数据绑定,继承,动画和默认 值,您应该将它们实现为依赖属性。“
这些是完全使用WPF提供的所有资源的正确属性类型
看看这些链接
http://msdn.microsoft.com/en-us/library/system.windows.dependencyproperty(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/ms750428(v=vs.110).aspx
或者只是在google上查找Dependency Property WCF。
了解这些属性之间差异的另一个有用链接是
https://stackoverflow.com/a/3674727
我遇到类似问题时使用的。
希望它有所帮助!