C# WPF 我无法进行私有更新,但 public 会
C# WPF I cannot get private to update but public will
对此我很是疑惑,搜索了也没有找到答案。我确定我没有正确理解某些东西。你能给我解释一下吗?
我有一个视图和一个视图模型。在视图中我有一个 Textblock
<TextBlock
Grid.Row="4"
Grid.Column="5"
Grid.ColumnSpan="3"
IsEnabled="{Binding Enable, Mode=OneWay}"
Margin="5,10,5,10">
<Run Text="File: "/>
<Run Text="{Binding FilePathName}"/>
</TextBlock>
在我的视图顶部
d:DataContext="{d:DesignInstance d:Type=viewModels:MainWindowViewModel}"
代码后面我也加了
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
我不想在此处添加 DataContext,但一开始它似乎可以正常工作,但现在我不确定是否需要它,我将尝试删除它。
我想我理解这部分,View 中的数据将从 ViewModel 中名为 FilePathName 的项目中刷新。
现在在视图模型中,我为 FilePathName 创建了“get and set”:
private string _filepathname;
public string FilePathName
{
get => _filepathname;
set
{
if (_filepathname != value)
{
_filepathname = value;
OnPropertyChanged();
}
}
}
现在我的理解肯定有点模糊了。我认为在 ModelView 中我将只使用私有字符串。这意味着当我像这样更改它的值时:
_filepathname = “MyNewName”;
然后 PropertyChanged 将看到此更改并将通过 public FilePathName 更新视图。但是,如果我使用 FileOpenDialog 并打开一个文件,然后说
if (openFileDialog.FileName != "")
{
_filepathname = openFileDialog.FileName;
ProcessFile();
}
我在这里使用的是私有的,但它永远不会更新。如果我在“获取和设置”中放置一个断点,我们永远不会去那里,所以 UI 永远不会更新。
但是我在 ProcessFile() 中使用
StreamReader sr = new StreamReader(_filepathname);
我确实读到了正确的文件。我可以理解,因为它也是私有的。但是……如果我现在将 private 更改为 public 如下
if (openFileDialog.FileName != "")
{
FilePathName = openFileDialog.FileName;
ProcessFile();
}
我现在更新 UI 并打开正确的文件进行阅读。似乎有时我需要使用 private 有时 public 才能使其工作。为什么?
第二个问题是为什么 isEnabled 似乎不适用于 TextBlock。我让它在按钮和文本框上工作。我在 TextBlock 中使用它如下,您可以在上面进一步查看它。
IsEnabled="{Binding Enable, Mode=OneWay}"
感谢所有帮助。
这不是那样的。
如果是,为什么我们需要属性?
这个:
myString = "new value"
ONLY 给变量赋值。就这样。当您使用 属性 执行此操作时,将调用 属性 setter,因此:
if(myString != value)
{
myString = value; //new value will be assigned to variable
OnPropertyChanged(); //property changed will be called
}
当你给变量赋值时,你就可以读取它,这就是发生的事情。
该变量称为“支持字段”。它在那里是因为必须有一些变量来存储一个值。如果你这样声明 属性:
public string MyString {get; set;}
在幕后,编译器还创建了这样的支持字段,最后它的工作方式如下:
string __myString;
public string MyString
{
get {return __myString;}
set {__myString = value;}
}
所以,如您所见,这只是一种合成糖。如果你想获得更多的属性(比如 call 属性 changed),你必须自己创建这样的 bakcing 字段。
此外,属性 本身不存储任何值。把它想象成一种方法。实际上有两种方法 - 一种是将值赋给变量,另一种是 returns 值:
public void SetMyString(string value)
{
myString = value;
}
public string GetMyString()
{
return myString;
}
因为属性atall也是某种合成糖
所以总结一下:
string myString;
public string MyString
{
get {return myString;}
set
{
if(myString != value)
{
myString = value;
OnPropertyChanged();
}
}
}
///
myString = "NewValue"; //<-- only assigns value to variable myString
MyString = "NewValue"; //<-- assings value to variable myString AND calls OnPropertyChanged - because that's how you property setter looks like.
您的视图和视图模型是两个不同的类。
当您更改视图模型的私有字段时,您的视图无法知道是否未收到通知。在 属性 setter 中调用 OnPropertyChanged()
时通知视图。修改字段时不会调用 属性 setter。阅读 了解更多详情。
要回答你的第二个问题,IsEnabled
不是你正在寻找的 属性,因为它禁用了 UI 元素,但没有隐藏它。您需要为此更改可见性 属性(使用转换器)。
以下是我的做法(有其他简化):
<!-- in application or control resources -->
<BooleanToVisibilityConverter x:Key="BooleanToVisibility" />
<TextBlock Grid.Row="4"
Grid.Column="5"
Grid.ColumnSpan="3"
Text="{Binding FilePathName, StringFormat=File: {0}}"
Visibility="{Binding Enable, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}"
Margin="5,10"/>
对此我很是疑惑,搜索了也没有找到答案。我确定我没有正确理解某些东西。你能给我解释一下吗?
我有一个视图和一个视图模型。在视图中我有一个 Textblock
<TextBlock
Grid.Row="4"
Grid.Column="5"
Grid.ColumnSpan="3"
IsEnabled="{Binding Enable, Mode=OneWay}"
Margin="5,10,5,10">
<Run Text="File: "/>
<Run Text="{Binding FilePathName}"/>
</TextBlock>
在我的视图顶部
d:DataContext="{d:DesignInstance d:Type=viewModels:MainWindowViewModel}"
代码后面我也加了
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
我不想在此处添加 DataContext,但一开始它似乎可以正常工作,但现在我不确定是否需要它,我将尝试删除它。
我想我理解这部分,View 中的数据将从 ViewModel 中名为 FilePathName 的项目中刷新。
现在在视图模型中,我为 FilePathName 创建了“get and set”:
private string _filepathname;
public string FilePathName
{
get => _filepathname;
set
{
if (_filepathname != value)
{
_filepathname = value;
OnPropertyChanged();
}
}
}
现在我的理解肯定有点模糊了。我认为在 ModelView 中我将只使用私有字符串。这意味着当我像这样更改它的值时:
_filepathname = “MyNewName”;
然后 PropertyChanged 将看到此更改并将通过 public FilePathName 更新视图。但是,如果我使用 FileOpenDialog 并打开一个文件,然后说
if (openFileDialog.FileName != "")
{
_filepathname = openFileDialog.FileName;
ProcessFile();
}
我在这里使用的是私有的,但它永远不会更新。如果我在“获取和设置”中放置一个断点,我们永远不会去那里,所以 UI 永远不会更新。
但是我在 ProcessFile() 中使用
StreamReader sr = new StreamReader(_filepathname);
我确实读到了正确的文件。我可以理解,因为它也是私有的。但是……如果我现在将 private 更改为 public 如下
if (openFileDialog.FileName != "")
{
FilePathName = openFileDialog.FileName;
ProcessFile();
}
我现在更新 UI 并打开正确的文件进行阅读。似乎有时我需要使用 private 有时 public 才能使其工作。为什么?
第二个问题是为什么 isEnabled 似乎不适用于 TextBlock。我让它在按钮和文本框上工作。我在 TextBlock 中使用它如下,您可以在上面进一步查看它。
IsEnabled="{Binding Enable, Mode=OneWay}"
感谢所有帮助。
这不是那样的。 如果是,为什么我们需要属性?
这个:
myString = "new value"
ONLY 给变量赋值。就这样。当您使用 属性 执行此操作时,将调用 属性 setter,因此:
if(myString != value)
{
myString = value; //new value will be assigned to variable
OnPropertyChanged(); //property changed will be called
}
当你给变量赋值时,你就可以读取它,这就是发生的事情。 该变量称为“支持字段”。它在那里是因为必须有一些变量来存储一个值。如果你这样声明 属性:
public string MyString {get; set;}
在幕后,编译器还创建了这样的支持字段,最后它的工作方式如下:
string __myString;
public string MyString
{
get {return __myString;}
set {__myString = value;}
}
所以,如您所见,这只是一种合成糖。如果你想获得更多的属性(比如 call 属性 changed),你必须自己创建这样的 bakcing 字段。
此外,属性 本身不存储任何值。把它想象成一种方法。实际上有两种方法 - 一种是将值赋给变量,另一种是 returns 值:
public void SetMyString(string value)
{
myString = value;
}
public string GetMyString()
{
return myString;
}
因为属性atall也是某种合成糖
所以总结一下:
string myString;
public string MyString
{
get {return myString;}
set
{
if(myString != value)
{
myString = value;
OnPropertyChanged();
}
}
}
///
myString = "NewValue"; //<-- only assigns value to variable myString
MyString = "NewValue"; //<-- assings value to variable myString AND calls OnPropertyChanged - because that's how you property setter looks like.
您的视图和视图模型是两个不同的类。
当您更改视图模型的私有字段时,您的视图无法知道是否未收到通知。在 属性 setter 中调用 OnPropertyChanged()
时通知视图。修改字段时不会调用 属性 setter。阅读
要回答你的第二个问题,IsEnabled
不是你正在寻找的 属性,因为它禁用了 UI 元素,但没有隐藏它。您需要为此更改可见性 属性(使用转换器)。
以下是我的做法(有其他简化):
<!-- in application or control resources -->
<BooleanToVisibilityConverter x:Key="BooleanToVisibility" />
<TextBlock Grid.Row="4"
Grid.Column="5"
Grid.ColumnSpan="3"
Text="{Binding FilePathName, StringFormat=File: {0}}"
Visibility="{Binding Enable, Mode=OneWay, Converter={StaticResource BooleanToVisibility}}"
Margin="5,10"/>