XAML, ListBox, ListBoxItems - c

I am trying to get data on mouse click events. In item.content I see the necessary data, but it does not get them. I need to get the values of this object ... but I don’t know how. I would be very grateful for your advice or assistance.
public partial class MainWindow : Window
{
class Room_List
{
public string Name { get; set; }
public string IP { get; set; }
public string Status { get; set; }
public string other { get; set; }
public Room_List() { }
public Room_List(string name, string ip, string status)
{
Name = name;
IP = ip;
Status = status;
}
}
ObservableCollection<Room_List> data_room_list = new ObservableCollection<Room_List>();
/*ObservableCollection<Conference_Room> data_conference_room = new ObservableCollection<Conference_Room>();*/
public MainWindow()
{
InitializeComponent();
//this.DataContext = this;
listbox_room_list.ItemsSource = data_room_list;
//входные тестовые данные
data_room_list.Add(new Room_List("Переговорная 101", "10.45.130.1", "fsdf"));
data_room_list.Add(new Room_List("Переговорная 102", "10.45.130.2", "fs12df"));
data_room_list.Add(new Room_List("Переговорная 103", "10.45.130.3", "fsf21df"));
data_room_list.Add(new Room_List("Переговорная 104", "10.45.130.4", "fsderf"));
data_room_list.Add(new Room_List("Переговорная 105", "10.45.130.5", "fsagsddf"));
}
private void PlaceholdersListBox_OnPreviewMouseDown2(object sender, MouseButtonEventArgs e)
{
var item = ItemsControl.ContainerFromElement(sender as ListBox, e.OriginalSource as DependencyObject) as ListBoxItem;
if (item != null)
{
// ListBox item clicked - do some cool things here
} }
private void listBox2_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
string str = listbox_room_list.SelectedValue.ToString();
} } }

it`s was easy...but not for me, I was prompted :)
Room_List room_List = (Room_List)Item.Content;

Related

INotifyPropertyChanged won't update grid in the window [duplicate]

This question already has answers here:
INotifyPropertyChanged WPF
(3 answers)
using of INotifyPropertyChanged
(3 answers)
Closed last year.
I've been this for a while now but I can't seem to be figuring out why my code won't update the window. The events are called and the invoke methods are invoked, but still, my window won't update
public class RaceContext : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Race CurrentRace { get; set; }
public string TrackName { get => CurrentRace == null ? "" : "Track name : " + CurrentRace.Track.Name; }
public List<IParticipant> Participants { get; set; }
public ObservableCollection<DriverListView> DriverListViews
{
get { return _DriverListViews; }
set { _DriverListViews = value; OnPropertyChanged(nameof(DriverListViews)); }
}
public ObservableCollection<DriverListView> _DriverListViews = new ObservableCollection<DriverListView>();
public void OnNextRace(object sender, NextRaceEventArgs e)
{
CurrentRace = e.Race;
e.Race.DriverChanged += OndriversChanged;
e.Race.DriverMoved += OnDriverMoved;
DriverListViews = new ObservableCollection<DriverListView>();
CurrentRace.Participants.ForEach(item =>
{
DriverListViews.Add(new DriverListView()
{
Driver = item
});
});
OnPropertyChanged();
}
public void OndriversChanged (object sender, DriversChangedEventArgs e)
{
Participants = CurrentRace.Participants;
e.DriverTimers.ForEach(timer =>
{
var view = DriverListViews.Where(item => item.Driver.Equals(timer.Driver)).First();
view.RaceStopwatch = timer.TotalRaceTimer.Elapsed;
view.LapStopwatch = timer.LapTimer.Elapsed;
});
OnPropertyChanged(nameof(DriverListViews));
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
This is the list view class
public class DriverListView
{
public IParticipant Driver { get; set; }
public int Position { get; set; }
public TimeSpan RaceStopwatch { get; set; }
public int LapCount { get; set; }
public TimeSpan LapStopwatch { get; set; }
public string LapPercentage { get; set; }
public int SectionCount { get; set; }
public string ParticipantName { get => Driver.Name; }
public TeamColors TeamColor { get => Driver.TeamColor; }
public int ParticpantPoints { get => Driver.Points; }
}
So when OnDriverChanged is called, the INotifyPropertyChanged is called. the window does not update the records
Thanks

WPF: How to notify the modification of an interface that changes in a DLL on the bindings side

How to notify the modification of an interface that changes in a DLL on the bindings side.
To explain:
Dll code is not editable:
public interface IPlayer
{
int Id { get; }
string Name { get; }
Settings Settings { get; }
PlayerCategory Category { get; }
}
public class TennisPlayer: IPlayer
{
public virtual int Id { get; }
public virtual string Name { get; set; }
public Tennisman(int id, string name)
{
Id = id;
Name = name;
}
public Settings Settings { get; set; }
public PlayerCategory Category { get; set; }
}
My code:
public partial class PlayerItem : NotifyUserControl
{
private DispatcherTimer timer = new DispatcherTimer();
public static readonly DependencyProperty PlayerProperty =
DependencyProperty.Register("Player", typeof(IPlayer),
typeof(PlayerItem),
new PropertyMetadata(null, OnCaptionPropertyChanged));
public IPlayer Player
{
get { return (IPlayer)GetValue(PlayerProperty); }
set
{
SetValue(PlayerProperty, value);
}
}
public string PlayerName
{
get => Player != null ? Player.Name : "";
set => OnPropertyChanged();
}
public PlayerItem()
{
InitializeComponent();
timer.Interval = new TimeSpan(0, 0, 4);
timer.Tick += Timer_Tick;
timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
OnPropertyChanged(nameof(PlayerName));
}
The external dll gives me player classes( for example: tennisman, footballer...) based on the same interface.
But I don't know it and I don't have to do class by class.
I must be missing something huge, but I managed to find nothing in my research.

WPF: set log level and refresh collection after changing

So I have form that show my Application Log.
This is my Log model:
public class LogEntry : IComparable<LogEntry>
{
public string DateTime { get; set; }
public int Index { get; set; }
public string Source { get; set; }
public Level Level { get; set; }
public string Message { get; set; }
public int CompareTo(LogEntry other)
{
return DateTime.CompareTo(other.DateTime);
}
}
public enum Level
{
All = 0,
Debug,
Info,
Warn,
Error,
Fatal,
Off
}
Log Helper
This is my LogHelper class that add the current LogEvent according the level that the user selected:
public static class LogHelper
{
public static ObservableCollection<LogEntry> LogEntries { get; set; }
public static bool AddLogToList { get; set; }
private static int _level;
private static int _index;
private static string _formatPattern = "yyyy-MM-dd HH:mm:ss,fff";
public static void SetLevel(Level level)
{
_level = (int)level;
}
public static void AddLog(Level level, string message, string className, string methodName)
{
if (LogEntries == null)
LogEntries = new ObservableCollection<LogEntry>();
if (AddLogToList)
{
int levelValue = (int)level;
if (levelValue >= _level)
{
Application.Current.Dispatcher.Invoke(new Action(() =>
{
if (LogEntries.Count == 1000)
LogEntries.RemoveAt(LogEntries.Count - 1);
LogEntry logEntry = new LogEntry()
{
DateTime = DateTime.Now.ToString(_formatPattern),
Index = _index++,
Level = level,
Source = className + "\\" + methodName,
Message = message.Trim()
};
LogEntries.Insert(0, logEntry);
}));
}
}
}
}
So I am add LogEvent into my list that contains up ti 1000 entries.
Now I want to be able to filter and show my only the relevant LogEvent Level.
So I added ComboBox with all my LogEvent levels and subscribe to its SelectionChanged event:
private void cbLogLevel_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
int index = cbLogLevel.SelectedIndex;
LogHelper.SetLevel((Level)index);
lvLogger.ItemsSource = LogHelper.LogEntries.Where(m => m.Level == (Level)index).ToList();
}
So after this SelectionChanged event I can see the relevant LogEvent level but my only issue is the new LogEvent not shows.
Maybe I need kind of refresh to my collection or something else ?
You are creating a new List<LogEntry> and setting the ItemsSource property to this one in your event handler. This means that lvLogger will no longer be connected to the ObservableCollection.
Instead of resetting the ItemsSource, you could filter the view:
private void cbLogLevel_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
int index = cbLogLevel.SelectedIndex;
Level level = (Level)index;
LogHelper.SetLevel(level);
var collectionView = CollectionViewSource.GetDefaultView(lvLogger.ItemsSource);
collectionView.Filter = x =>
{
LogEntry logEntry = x as LogEntry;
return logEntry != null && logEntry.Level == level;
};
}

I need your suggestion regarding loop in Model to ViewModel MVVM

I'am new to WPF and MVVM and I was given the task to continue working on one of the unfinished project that is made using the said technology. I've written a sample code below that is similar to the structure of the project.
My concern is, the loop used in GetBookPages() to display the details on the grid might take some time to finish.
public class BookModel
{
public string BookTitle { get; set; }
public List<BookDetailModel> BookDetails { get; set; }
}
public class BookDetailModel
{
public int Pages { get; set; }
public string Others { get; set; }
// ....
}
public class BookViewModel : INotifyPropertyChanged
{
private BookModel _model;
private ObservableCollection<BookDetailViewModel> _bookDetailSource;
private BookService _service;
public BookViewModel()
{
_model = new BookModel();
_service = new BookService();
GetBookPages();
}
/// <summary>
/// This is the item source of datagrid that is located in view
/// </summary>
public ObservableCollection<BookDetailViewModel> BookDetailSource
{
get { return _bookDetailSource; }
set
{
if (value == _bookDetailSource)
return;
_bookDetailSource = value;
OnPropertyChanged();
}
}
private void GetBookPages()
{
BookModel bookModel = _service.GetBookData();
var listOf = new List<BookDetailViewModel>();
bookModel.BookDetails.ForEach(e =>
{
// This is were the system's bottle neck is.
// can someone please suggests me a good work around.
listOf.Add(
new BookDetailViewModel
{
Others = e.Others,
// ....
});
});
BookDetailSource = new ObservableCollection<BookDetailViewModel>(listOf);
}
public string BookTitle
{
get { return _model.BookTitle; }
set
{
if (value == _model.BookTitle)
return;
_model.BookTitle = value;
OnPropertyChanged();
}
}
#region Property Change
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public class BookDetailViewModel : INotifyPropertyChanged
{
private BookDetailModel _model;
#region Constructor
public BookDetailViewModel()
{
_model = new BookDetailModel();
ViewPageDataCommand = new RelayCommand(x => ViewPageData());
RemovePageCommdand = new RelayCommand(x => RemovePage());
}
#endregion
#region Properties
public int Page
{
get { return _model.Pages; }
set
{
if (value == _model.Pages)
return;
_model.Pages = value;
OnPropertyChanged();
}
}
public string Others
{
get { return _model.Others; }
set
{
if (value == _model.Others)
return;
_model.Others = value;
OnPropertyChanged();
}
}
#endregion
// These are the button command inside the grid's row
public ICommand ViewPageDataCommand { get; private set; }
public ICommand RemovePageCommdand { get; private set; }
private void ViewPageData()
{
// view the page data by clicking the row button inside the grid
}
private void RemovePage()
{
// will remove the currently selected row inside the grid
}
#region Property Change
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public class BookService
{
public BookModel GetBookData()
{
var data = GetBookData(99);
data.BookDetails = GetBookDetail(99);
return data;
}
private BookModel GetBookData(int bookId)
{
// return 1 row only
}
private List<BookDetailModel> GetBookDetail(int bookId)
{
// return List<BookDetailModel> that might consists of more than 100 index's
}
}
I hope you understand what I mean. Your suggestion will be much appreciated. Thanks in advance!

WPF Datagrid get data on CheckboxChecked-Event

I've got a datagrid with a checkbox, name and email.
On CheckboxChecked I want to copy the email into another list or string.
How do I get the specific value from the checked row?
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
object row = lbxCC1.SelectedItem;
int columnIndex = lbxCC1.Columns.Single(c => c.Header.Equals("eMail")).DisplayIndex;
String eMail = (lbxCC1.SelectedCells[columnIndex].Column.GetCellContent(row) as TextBlock).Text;
MessageBox.Show(eMail);
}
Edit (09.09.2016):
Maybe I should show you a bit more code.
public class Person
{
public string Nachname { get; set; }
public string Vorname { get; set; }
public string eMail { get; set; }
public string Abteilung { get; set; }
}
public static class PersonService
{
public static List<Person> ReadFile(string filepath)
{
var lines = File.ReadAllLines(filepath);
var data = from l in lines.Skip(1)
let split = l.Split(';')
select new Person
{
Nachname = split[1],
Vorname = split[2],
eMail = split[31],
Abteilung = split[4],
};
return data.ToList();
}
}
I call it with:
lbxCC1.DataContext = PersonService.ReadFile(#"C:\Test.csv");
As I'm building the columns from code behind, I guess I have to bind them aswell am I right?
Sorry for this, but I'm new to datagrids :-)
I think this might help you:
Dim row As Data.DataRowView = DirectCast([yourDataGrid].SelectedItems(rowIndex), Data.DataRowView)
Then in your CheckBox_Checked Event:
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
MessageBox.Show(row("email"); 'Assuming the column name is email
}
This is IF your values are data-bound to the DataGrid.

Resources