У меня есть label, который в качестве контекста содержит объект Point. При изменении значения этого объекта label не обновляется. Как исправить.
internal class Point
{
private int x;
private int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public int X { get; set; }
public int Y { get; set; }
public override string ToString()
{
return $"{x}, {y}";
}
}
internal static class PointManager
{
public static Point Point => new Point(0,0);
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
PointManager.Point.X = 1;
//как сделать, чтобы на экране отобразилось 1,0
}
}
часть XAML:
<Border Grid.Column="2" BorderBrush="Black" BorderThickness="1" CornerRadius="10" Margin="3" Padding="10" Background="SandyBrown">
<Label HorizontalAlignment="Center" VerticalAlignment="Center">
<Binding Source="{x:Static local:PointManager.Point}" />
</Label>
</Border>
В вашем коде несколько проблем, во-первых, этот код:
public static Point Point => new Point(0,0);
при каждом обращении создает новый экземпляр, надо переписать так:
public static Point Point { get; } = new Point(0,0);
Во-вторых, привязка нормально работает только со свойствами, вы же надеетесь на неявный вызов ToString()
поэтому первое что надо сделать, это или добавить в класс Point
еще одно свойство:
public string Value => $"{x}, {y}";
и привязаться непосредственно к нему:
<Binding Source="{x:Static local:PointManager.Point}" Path="Value" />
Либо, что более правильно т.к. модель не должна подстраиваться под представление, привязаться к уже имеющимся свойствам (напишите вместо Label
):
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<Run Text="{Binding X, Source={x:Static local:PointManager.Point}}"/>,
<Run Text="{Binding Y, Source={x:Static local:PointManager.Point}}"/>
</TextBlock>
В-третьих, ваше представление никак не может догадаться, что данные изменились и их пора перечитать, поэтому либо надо сказать привязке чтобы она обновила свою цель, например, так:
<!--Добавил Name-->
<Run Name="MyText" Text="{Binding X, Source={x:Static local:PointManager.Point}}"/>,
и в методе:
private void Window_KeyDown(object sender, KeyEventArgs e)
{
PointManager.Point.X = 1;
MyText.GetBindingExpression(Run.TextProperty).UpdateTarget();
}
Либо, что более правильно, ваши классы, к которым вы выполняете привязки (это будет VM слой уже, а не модель – почитайте про паттерн MVVM), должны оповещать об изменениях свойств. Для этого в стандартной библиотеке существует интерфейс INotifyPropertyChanged
, с которым прекрасно работает WPF.
Обычно реализация INotifyPropertyChanged
выглядит примерно так:
abstract class Vm : INotifyPropertyChanged
{
protected bool Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
NotifyPropertyChanged(propertyName);
return true;
}
protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Тогда, ваш класс превращается в такой:
internal class Point : Vm
{
private int x;
private int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public int X { get => x; set { Set(ref x, value); } }
public int Y { get => y; set { Set(ref y, value); } }
}
Всё, привязка получит оповещение PropertyChanged
и обновится самостоятельно, без явного ей на то указания.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Собственно существует https://duraspaceorg/dspace/ Возникла необходимость из c# сохранять файлы в данном хранилище настроенном на сервере организации
Всем приветВ contact form 7 , плагине WordPress, есть поле messages
Имеется собственный канал и бот, в канал публикуются статьи в виде превью с кнопкой Instant view для просмотра целиком