我已经集成了一个小型应用程序和一个控制台窗口,该窗口将信息传递给用户。
在我看来,有一个ItemControl有一个TextBlock作为模板,显示“ConsoleText”与所需的颜色“FontColour”:
<Window x:Class="MyApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helper="clr-namespace:MyApplication.Helpers"
mc:Ignorable="d"
Title="MainWindow" Height="600" Width="800" MinHeight="600" MinWidth="800">
<Grid>
<DockPanel Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="3" Grid.RowSpan="4" Background="Black">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" helper:ScrollViewerExtension.AutoScroll="True">
<ItemsControl ItemsSource="{Binding logger.ConsoleOutput}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ConsoleText}" Foreground="{Binding FontColour}" FontSize="14"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</Grid>
</Window>
我的代码隐藏文件只包含DataContext:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
}
视图的“我的视图模式”有三个信息:
1.示例化MyLogicClass,它在另一个项目中结构化,并作为引用给出。
- ConsoleOutputList被示例化,以便稍后能够在视图中显示“ConsoleOutput”。
1.该按钮不会显示在视图中,因为它在视图中不相关,并且可以正常工作。
这里是ViewModel:
public class MainWindowViewModel : ObservableObject
{
MyLogicClass myLogicClass = new MyLogicClass(null);
ConsoleOutputList logger = new ConsoleOutputList();
public MainWindowViewModel()
{
MyButtonCommand = new RelayCommand(o => Task.Run(() => myLogicClass.Test()));
}
public ICommand MyButtonCommand { get; }
}
ConsoleOutputList包含一个来自“ConsoleLine”的ObservableCollection(也在另一个项目中)。“ConsoleLine”可能在ctor中有一个字符串和一个SolidColorBrush(我认为这一个也不相关)。
public class ConsoleOutputList : ObservableObject
{
public ConsoleOutputList()
{
ConsoleOutput = new ObservableCollection<ConsoleLine>();
// For testing purposes I add a random entry to see if the binding in general works - but this doesn`t work neither
ConsoleOutput.Add(new ConsoleLine("Test", Brushes.Green));
}
public ObservableCollection<ConsoleLine> consoleOutput { get; set; }
public ObservableCollection<ConsoleLine> ConsoleOutput
{
get
{
return consoleOutput;
}
set
{
consoleOutput = value;
}
}
//Used to add new lines to the ObservableCollection
public void WriteToConsole(object msg, SolidColorBrush fontColour)
{
ConsoleOutput.Add(new ConsoleLine(msg, fontColour));
}
}
这个类用于所有的应用程序逻辑(也在另一个项目中)。作为一个测试,我在这里使用Test()方法来简单地添加一个文本。
public class MyLogicClass
{
ConsoleOutputList Logger = new ConsoleOutputList();
public void Test()
{
Logger.WriteToConsole($"Test", Brushes.Gray);
}
}
现在我有两个问题:
1.我在ConsoleOutputList的ctor中添加了一个新元素作为测试,以查看我的视图是否正常工作=>但不工作
1.我使用Test()方法来简单地测试向ObservableCollection添加新项,以查看它们在添加=>后是否会显示出来,当然这也不起作用
是的,我知道-我创建了两个ConsoleOutputList示例,这是不正确的(这是第二个问题的原因)。但我不知道如何做得更好,因为我需要从代码中的任何地方访问WriteToConsole()。(可能会更改为静态。但是我如何解决第一个问题,以及它如何处理静态属性,并在视图中显示它们。
更新:即使我将所有内容都更改为静态,“测试”行也会显示为绿色,但之后添加的所有内容都不会显示在GUI中:Visual Studio
1条答案
按热度按时间6tr1vspr1#
在WPF中,您不能绑定到方法或字段。您必须绑定到公共属性(请参阅Microsoft文档:绑定源类型,以了解有关受支持的绑定源的更多信息)。
要解决问题1),您必须将
MainWindowViewModel.logger
字段实现为公共属性。如果预期属性要更改,则必须引发INotifyPropertyChanged.PropertyChanged
事件。要修复2),您必须在整个应用程序中分发
ConsoleOutputList
的共享示例。将其公开为静态示例是一种解决方案,但通常不推荐。更好的解决方案是将一个共享示例传递给依赖于ConsoleOutputList
的每个类型的构造函数。固定的解决方案可以如下所示:
MainWindowViewModel.cs
MyLogicClass.cs
MainWindow.xaml.cs
App.xaml
App.xaml.cs
也不要将
ItemsControl
Package 成ScrollViewer
。使用ListBox
代替。ListBox
是一个增强的ItemsControl
,默认情况下启用了ScrollViewer
和UI虚拟化。如果您希望生成许多日志条目,那么列表中将出现许多条目。如果不使用UI虚拟化,ItemsControl
将降低GUI的性能/响应能力。要允许从后台线程或非UI线程更新集合
ConsoleOutput
,您可以使用Dispatcher
来更新集合(在这种情况下不推荐):或者配置绑定引擎将集合的
CollectionChanged
事件封送到调度器线程。由于关键对象是一个用作绑定源的集合,因此我建议通过调用静态
BindingOperations.EnableCollectionSynchronization
方法来配置绑定引擎。必须在调度器线程上调用该方法:ConsoleOutputList.cs