WPF how to see last added text line in TexBox - wpf-controls

I would like simmulate Console text output in my WPF app
but when I add new lines in TextBox I should use scroll bar to see last added text but I want to see last added text but for firsts lines use scroll bar
<TextBox TextWrapping="Wrap" AcceptsReturn="True" VerticalScrollBarVisibility="Auto"
Text="{Binding Path=Data, Mode=TwoWay}" />`

Use the ScrollToLine method of TextBox (and the LineCount property to know how many lines there are) after adding text in order to make sure that the just-added line is visible.

Please consider scrolling the textbox directly from code behind like this (e.g. when text changes):
private void SampleTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (SampleTextBox.LineCount != -1)
{
SampleTextBox.ScrollToLine(SampleTextBox.LineCount - 1);
}
}
Please tell me if this helps.

thanks for answers: I expected to do it from XAML but as I undestood it's only possible from code behind
so here is my implimentation now with checkbox for stop ScrollToEnd function:
public partial class MainWindow : Window
{
private bool isScrollToEnd;
Timer timer;
public double WaitTime
{
get { return waitTime / 1000; }
set { waitTime = value * 1000; }
}
private double waitTime;
public MainWindow()
{
InitializeComponent();
isScrollToEnd = true;
waitTime = 5000;
tbWaitTime.DataContext = this;
timer = new Timer(waitTime);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
}
// событие изменения текста в контроле tbConsole
private void tbConsole_TextChanged(object sender, TextChangedEventArgs e)
{
if (tbConsole.LineCount != -1 && isScrollToEnd)
{
tbConsole.ScrollToLine(tbConsole.LineCount - 1);
cbIsScrolling.IsChecked = false;
}
}
private void cbIsScrolling_Click(object sender, RoutedEventArgs e)
{
if ((bool)cbIsScrolling.IsChecked)
{
isScrollToEnd = !(bool)cbIsScrolling.IsChecked;
isScrollToEnd = false;
timer.Interval = waitTime;
timer.Start();
return;
}
isScrollToEnd = true;
timer.Stop();
cbIsScrolling.IsChecked = false;
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
timer.Stop();
isScrollToEnd = true;
}
}
and here is XAML code:
<StackPanel Grid.Column="1" Grid.Row="2" Grid.ColumnSpan="2" Grid.RowSpan="2">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,3,10,2" VerticalAlignment="Top">
<Label Content="Stop autoscrolling for:" />
<TextBox Name="tbWaitTime" Text="{Binding Path=WaitTime}"
MinWidth="25" MaxWidth="50" Margin="5,0,0,0" />
<Label Content="sec."/>
<CheckBox Name="cbIsScrolling"
HorizontalAlignment="Right" VerticalAlignment="Center"
Click="cbIsScrolling_Click" />
</StackPanel>
<TextBox Name="tbConsole"
Background="LightGoldenrodYellow" Padding="5" Height="100"
VerticalScrollBarVisibility="Auto"
TextWrapping="Wrap"
AcceptsReturn="True"
Text="{Binding Path=Data, Mode=TwoWay}" TextChanged="tbConsole_TextChanged" />
</StackPanel>

Related

.NET MAUI - CollectionView not updating data [duplicate]

I have code that is a sample bowling recap where 3 games are entered and are summarized in a Series column. The problem that I am experiencing is the Series column is not getting updated as I anticipate. Obviously, I am doing something wrong but can not see what I am doing wrong. Below is the code that supports the application:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="HoriView.MainPage">
<StackLayout>
<ScrollView>
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
<Image
Source="dotnet_bot.png"
HeightRequest="200"
HorizontalOptions="Center" />
<Label
Text="Hello, Bowlers!"
FontSize="32"
HorizontalOptions="Center" />
<Label
Text="Bowling Recap Snippet"
FontSize="18"
HorizontalOptions="Center" />
</VerticalStackLayout>
</ScrollView>
<ScrollView>
<HorizontalStackLayout HorizontalOptions="Center">
<CollectionView SelectionMode="Single" ItemsSource="{Binding scores}" ItemsLayout="HorizontalList">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding Game}" FontSize="Medium" WidthRequest="83" VerticalOptions="Center" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End"></Label>
<Entry Grid.Row="1" Text="{Binding Score}" TextChanged="UpdateGame" Keyboard="Numeric" ReturnType="Next" Placeholder="Game" WidthRequest="83" FontSize="Medium" ></Entry>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</HorizontalStackLayout>
</ScrollView>
</StackLayout>
</ContentPage>
using System.Collections.ObjectModel;
namespace HoriView;
public partial class MainPage : ContentPage
{
public ObservableCollection<Games> scores { get; set; }
string header = "Game";
public MainPage()
{
InitializeComponent();
scores= new ObservableCollection<Games>();
for(int i=0; i<4; i++)
{
if (i == 3)
{
header = "Series";
}
else
{
header = "Game" + (i+1).ToString();
}
scores.Add(new Games()
{
Game=header,
Score=0
});
}
BindingContext = this;
}
public void UpdateGame(object sender, TextChangedEventArgs e)
{
scores[scores.Count-1].Score = 0;
for(int i=0; i< scores.Count-1; i++)
{
scores[scores.Count - 1].Score += scores[i].Score;
}
}
}
public class Games
{
public string Game { get; set; }
public int Score { get; set; }
}
Any help would be appreciated. Thanks.
Your Games class doesn't implement the INotifyPropertyChanged interface.
You can either implement that manually:
public class Games : INotifyPropertyChanged
{
private string _game;
public string Game
{
get => _game;
set
{
if(_game == value) return;
_game = value;
OnPropertyChanged();
}
}
private int _score;
public int Score
{
get => _score;
set
{
if(_score == value) return;
_score = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Alternatively, you could also inherit from ObservableObject from the MVVM Community Toolkit and then simply write the following using Source Generators:
public partial class Games : ObservableObject
{
[ObservableProperty]
private string _game;
[ObservableProperty]
private int _score;
}
In this case, you only define the backing fields and the Source Generators will create the uppercase, observable properties Game and Score for you.

WPF TreeView in ControlTemplate - Handling Item Expanded

I am creating a Custom Control and in the control template I have a TreeView class in it.
<Style TargetType="{x:Type local:MyControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyControl}">
<Border>
<TreeView ItemsSource="{Binding TreeDataItems, RelativeSource={RelativeSource TemplatedParent}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="TreeViewItem.Expanded">
<i:InvokeCommandAction Command="{Binding TreeItemExpandedCommand, RelativeSource={RelativeSource TemplatedParent}}"
CommandParameter="{Binding}">
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</TreeView>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
In the code file for the custom control I have this command:
private ICommand _TreeItemExpandedCommand;
public ICommand TreeItemExpandedCommand
{
get
{
if (_TreeItemExpandedCommand == null)
_TreeItemExpandedCommand = new RelayCommand(p => TreeItemExpandedExecuted(p));
return _TreeItemExpandedCommand;
}
}
private void TreeItemExpandedExecuted(object args)
{
}
I have also tried
<TreeView TreeViewItem.Expanded="TreeViewItem_Expanded">
...
</TreeView/>
but neither gets fired.
How can I handle the TreeView's Expanded event INSIDE my custom control's code file?
Thanks
I am not pro Wpf programmer, but i manage to figure out the solution for your problem. The problem with your code, is that the event is not exactly belongs to TreeView itself, but rather the elements inside it (Items property).
So this wont work:
...
<i:EventTrigger EventName="TreeViewItem.Expanded">
...
On the other hand, this would work:
...
<i:EventTrigger EventName="SelectedItemChanged">
...
because this event belongs to TreeView
Basicly, what you need to do is subscribe for the Expanded event of all the TreeViewItems in the TreeView. You can do this from code behind.
Here is how i did it:
public class MyCustomControl : Control
{
public TreeView MyTreeView { get; set; }
public static readonly DependencyProperty TreeViewItemListProperty = DependencyProperty.Register("TreeViewItemList",
typeof(List<StorageItem>),
typeof(MyCustomControl),
new UIPropertyMetadata(null));
public List<StorageItem> TreeViewItemList
{
get { return (List<StorageItem>)GetValue(TreeViewItemListProperty); }
set { SetValue(TreeViewItemListProperty, value);}
}
public static readonly RoutedEvent MyEventRoutedEvent = EventManager.RegisterRoutedEvent("MyEvent",
RoutingStrategy.Bubble,
typeof(EventHandler<RoutedEventArgs>),
typeof(MyCustomControl));
public event RoutedEventHandler MyEvent
{
add { this.AddHandler(MyEventRoutedEvent, value); }
remove { this.RemoveHandler(MyEventRoutedEvent, value); }
}
public override void OnApplyTemplate()
{
MyTreeView = Template.FindName("MyTreeView", this) as TreeView;
MyTreeView.Items.CurrentChanged += Items_CurrentChanged;
base.OnApplyTemplate();
}
private void Items_CurrentChanged(object sender, EventArgs e)
{
SubscribeAllTreeViewItems(MyTreeView);
}
private void SubscribeAllTreeViewItems(ItemsControl treeViewItem)
{
foreach (object item in treeViewItem.Items)
{
TreeViewItem treeItem = treeViewItem.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
if (treeItem != null)
{
SubscribeAllTreeViewItems(treeItem);
treeItem.Expanded += TreeViewItem_Expanded;
}
}
}
private void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
{
RoutedEventArgs args = new RoutedEventArgs(MyEventRoutedEvent, this);
this.RaiseEvent(args);
}
static MyCustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
}
}
First we need to acquire our TreeView Control and subscribe the event if it gets items:
public override void OnApplyTemplate()
{
MyTreeView = Template.FindName("MyTreeView", this) as TreeView;
MyTreeView.Items.CurrentChanged += Items_CurrentChanged;
base.OnApplyTemplate();
}
Then, if this is fired, we know that our TreeView has Items in it, so we can cycle through its elements and subscribe for the event Expanded:
private void Items_CurrentChanged(object sender, EventArgs e)
{
SubscribeAllTreeViewItems(MyTreeView);
}
private void SubscribeAllTreeViewItems(ItemsControl treeViewItem)
{
foreach (object item in treeViewItem.Items)
{
TreeViewItem treeItem = treeViewItem.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
if (treeItem != null)
{
SubscribeAllTreeViewItems(treeItem);
treeItem.Expanded += TreeViewItem_Expanded;
}
}
}
After that, we are good to go! I also added code for to be able to subscribe for this event from outside the custom control:
public static readonly RoutedEvent MyEventRoutedEvent = EventManager.RegisterRoutedEvent("MyEvent",
RoutingStrategy.Bubble,
typeof(EventHandler<RoutedEventArgs>),
typeof(MyCustomControl));
public event RoutedEventHandler MyEvent
{
add { this.AddHandler(MyEventRoutedEvent, value); }
remove { this.RemoveHandler(MyEventRoutedEvent, value); }
}
....
....
private void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
{
RoutedEventArgs args = new RoutedEventArgs(MyEventRoutedEvent, this);
this.RaiseEvent(args);
}
So this way, you can subscribe it from outside like that:
<local:MyCustomControl TreeViewItemList="{Binding Path=Items}"
MyEvent="MyCustomControl_MyEvent"/>
Finally, here it is the .xaml
<Style TargetType="{x:Type local:MyCustomControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyCustomControl}">
<TreeView ItemsSource="{TemplateBinding TreeViewItemList}"
x:Name="MyTreeView">
<TreeView.Resources>
<!--Here we specify how to display a FolderItem-->
<HierarchicalDataTemplate DataType="{x:Type localviewmodels:FolderItem}"
ItemsSource="{Binding Path=Items}">
<TextBlock Text="{Binding Path=Name}"
Margin="0 0 35 0"/>
</HierarchicalDataTemplate>
<!--Here we specify how to display a FileItem-->
<DataTemplate DataType="{x:Type localviewmodels:FileItem}">
<TextBlock Text="{Binding Path=Name}"
Margin="0 0 35 0"/>
</DataTemplate>
</TreeView.Resources>
</TreeView>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
UPDATE
if you want to set TreeView items inside the custom Control, you should
subscribe the MyTreeView.Loaded event as well to catch the first time when it gets values.
i hope it helps!
If anything is not clear, feel free to ask, i am ready to help!

Updating a ListView with Xamarin.Forms

I am having an issue with list views on in a couple of my Xamarin Forms applications. One form is within a tabbed page setup, the other is a normal content page (different apps)
I have a class like this
public class SomeClass
{
public string StringOne {get;set;}
public string StringTwo {get;set;}
public int IntOne {get;set;}
}
In my Content page, I set up an ObservableCollection and add some data in. I then tell the list that SomeClass is my ItemSource. This produces the ListView correctly on all of my devices.
The problem is that when I change one of the properties, nothing on the ListView changes (so if say I have 3 objects in the Observable and remove one, the list still says 3 - or if I change a property in my second object, the second item on the ListView doesn't change either).
I have also tried to solve the problem by using a standard List and implement INotifyChanged within the class. Again though, the ListView doesn't alter when the List changes.
I know the data has altered as if I make a change to the object, come out and go back in, the data has changed in the UI.
Am I doing something wrong or is this a bug I need to putting into Bugzilla?
It will not change if you don't bind it and implement INotifyPropertyChanged interface.
Sample Code:
public class ObservableProperty : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class SomeClass:ObservableProperty
{
string stringOne;
string stringTwo;
int intOne;
public string StringOne
{
get{return stringOne;}
set
{
stringOne = value;
OnPropertyChanged("StringOne");
}
}
public string StringTwo
{
get{ return stringTwo;}
set
{
stringTwo = value;
OnPropertyChanged("StringTwo");
}
}
public int IntOne
{
get{ return intOne;}
set
{
intOne = value;
OnPropertyChanged("IntOne");
}
}
}
public class MainVM:ObservableProperty
{
ObservableCollection<SomeClass> items;
public ObservableCollection<SomeClass> items
{
get{return items;}
set
{
items = value;
OnPropertyChanged("Items");
}
}
public MainVM()
{
Items = new ObservableCollection<SomeClass>();
Items.Add(new SomeClass(){StringOne = "123", StringTwo = "test", IntOne =12});
}
public void CallMeForChangingProperty()
{
SomeClass item = Items[0];
item.StringOne = "Test1";
}
}
public class MainView
{
public MainView()
{
this.BindingContext= new MainVM()
}
}
< ListView ItemsSource="{Binding Items}" RowHeight="120">
< ListView.ItemTemplate>
< DataTemplate>
< ViewCell>
< ViewCell.View>
< StackLayout>
< Label Text= "StringOne" />
< Label Text= "StringTwo" />
< Label Text= "IntOne" />
</ StackLayout>
</ ViewCell.View>
</ ViewCell>
</ DataTemplate>
</ ListView.ItemTemplate>
</ ListView>
Answer given by #eakgul works like a charm for me.
I'll attach here what I've implemented, maybe it could help someone.
You have to set INotifyPropertyChanged both, to the ObservableColection and to it's itens.
I have a BaseViewModel with INotifyPropertyChanged as follows:
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
protected void SetProperty<T>(ref T backingField, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals( backingField, value)) return;
backingField = value;
OnPropertyChanged(propertyName);
}
}
On my BluetoothPage.xaml, first I set bindincontext to my BluetoothPageViewModel.cs and set the ListView ItemsSource and it's binded labels:
<ContentPage.BindingContext>
<viewmodel:BluetoothPageViewModel/>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout Padding="5,10">
<Button x:Name="Scan_Devices_Button"
Command="{Binding SearchNew_Button_Clicked}"/>
<ListView x:Name="DevicesList"
ItemsSource="{Binding BluetoothDevices}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
IsPullToRefreshEnabled="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Text="{Binding device.Device.NativeDevice.Name}"/>
<Label Grid.Column="1"
Text="{Binding device.Device.NativeDevice.Address, StringFormat='ID: {0}'}"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Text="{Binding device.Rssi, StringFormat='Power: {0:F2}dbm'}"/>
<Label Grid.Column="1"
Text="{Binding distance, StringFormat='Distance: {0:F2}m'}"/>
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
Then, in my BluetoothPageViewModel.cs I extend it with the BaseViewModel and declare ItemsSource BluetoothDevices with INotifyPropertyChanged. At this moment, everytime I change an item on the ObservableCollection BluetoothDevices, the ListView will be updated. But, If I made a change on an item inside the ObservableCollection, nothing will happen!
So, you must set INotifyPropertyChanged to it's itens.
Following is my BluetoothPageViewModel, which uses a class BluetoothPageModel in the PageModel BluetoothPageModel.cs
The BluetoothPageViewModel:
public class BluetoothPageViewModel : BaseViewModel
{
public BluetoothPageViewModel()
{
SearchNew_Button_Clicked = new Command(NewDevices_Button_Clicked_Event);
Scan_Devices_Button_BgColor = "#D6D7D7";
Scan_Devices_Button_Text = "Scan nearby devices";
}
#region Declarations
public List<IDevice> iDeviceList = new List<IDevice>();
public ObservableCollection<BluetoothPageModel> _bluetoothDevices = new ObservableCollection<BluetoothPageModel>();
public BluetoothPageModel _selectedItem;
public ObservableCollection<BluetoothPageModel> BluetoothDevices
{
get { return _bluetoothDevices; }
set { SetProperty(ref _bluetoothDevices, value); }
}
public BluetoothPageModel SelectedItem
{
get { return _selectedItem; }
set { SetProperty(ref _selectedItem, value); }
}
public ICommand SearchNew_Button_Clicked { get; private set; }
#endregion
#region Functions
private void NewDevices_Button_Clicked_Event(object obj)
{
// discover some devices
if (!CrossBleAdapter.Current.IsScanning)
{
BluetoothDevices.Clear();
iDeviceList.Clear();
var scanner = CrossBleAdapter.Current.Scan().Subscribe(scanResult =>
{
if (!iDeviceList.Contains(scanResult.Device))
{
iDeviceList.Add(scanResult.Device);
Device.BeginInvokeOnMainThread(() =>
{
BluetoothDevices.Add(new BluetoothPageModel
{
device = scanResult,
distance = Math.Pow(10, ((-68 - scanResult.Rssi) / 31.1474))
});
});
}
else
{
int ind = iDeviceList.IndexOf(scanResult.Device);
Device.BeginInvokeOnMainThread(() =>
{
BluetoothDevices[ind].device = scanResult;
BluetoothDevices[ind].distance = Math.Pow(10, ((-68 - scanResult.Rssi) / 31.1474));
});
}
});
}
else
{
CrossBleAdapter.Current.StopScan(); //When you want to stop scanning
}
}
#endregion
}
Finally, to be able to update data when you change a property of the BluetoothPageModel class:
public class BluetoothPageModel:BaseViewModel
{
public IScanResult _device;
public double _distance;
public IScanResult device
{
get { return _device; }
set { SetProperty(ref _device, value); }
}
public double distance
{
get { return _distance; }
set { SetProperty(ref _distance, value); }
}
}
Thanks to eakgul answer I could get it working. Hope it can help someone else.

Display a button when I tap a long list selector

I want to display a button, when I tap a long list selector in windows phone 8.
C#
this.DisplayedContacts = new ObservableCollection<string>();
this.DataContext = this.DisplayedContacts;
var contacts = new Contacts();
contacts.SearchCompleted += (s, e) =>
{
foreach (var contact in e.Results)
{
Debug.WriteLine(contact.PhoneNumbers.Any()? contact.PhoneNumbers.First().PhoneNumber: string.Empty);
this.DisplayedContacts.Add(contact.DisplayName + " - " +
(contact.PhoneNumbers.Any()
? contact.PhoneNumbers.First().PhoneNumber
: string.Empty));
}
};
contacts.SearchAsync(string.Empty, FilterKind.DisplayName, null);
}
public ObservableCollection<string> DisplayedContacts { get; set; }
private void LongListSelector_Tap_1(object sender,GestureEventArgs e)
{}
xaml code
<phone:LongListSelector FontSize="50" Foreground="Gray" Tap="LongListSelector_Tap_1" ItemsSource="{Binding}" Margin="0,77,0,0" />
User Visibility property to hide your list and show the Button.
Your XAML will look something like bellow:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" >
<phone:LongListSelector x:Name="LongList" Tap="LongListTap"/>
<Button x:Name="ActionButton" Visibility="Collapsed"/>
</Grid>
And event handler:
private void LongListTap(object sender, GestureEventArgs e)
{
LongList.Visibility = Visibility.Collapsed;
ActionButton.Visibility = Visibility.Visible;
}
what you have to this just set the visibilty of your button to visible like suppose your buttn name is "Mybutton" ..
private void LongListSelector_Tap_1(object sender,GestureEventArgs e)
{
Mybutton.Visibility = Visibility.visible;
}

horizontal line on wpftoolkit chart

I'm using the WPF toolkit to create a line graph.
Here's what I'm doing:
<Window x:Class="TempDataAnalyzer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" Loaded="Window_Loaded">
<Grid>
<chartingToolkit:Chart Name="lineChart" Title="Temperature" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<chartingToolkit:LineSeries DependentValuePath="Value" IndependentValuePath="Key" ItemsSource="{Binding}" IsSelectionEnabled="True"/>
</chartingToolkit:Chart>
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
List<KeyValuePair<int, int>> entries = new List<KeyValuePair<int, int>>();
entries.Add(new KeyValuePair<int, int>(0, 0));
entries.Add(new KeyValuePair<int, int>(1, 23));
entries.Add(new KeyValuePair<int, int>(2, 45));
entries.Add(new KeyValuePair<int, int>(3, 46));
entries.Add(new KeyValuePair<int, int>(4, 71));
lineChart.DataContext = entries;
}
}
this question was already asked, but i didnt understand the answer, could some one please provide me with an example

Resources