问:
how to remove numeric characters before any alphabetic characters
I have one variable which has values like this

```<code>VAL1="59809_RH_EA_TEST_1_P1_Q"
</code>```

or

```<code>VAL1="89292-RH_EA_TEST_1_P1_Q"
</code>```

How can I get only RH_EA_TEST_1_P1_Q using sed or any other bash command

答:
One way is to use Bash regex matching.

```<code>VAL1="59809_RH_EA_TEST_1_P1_Q"

if
  [[ $VAL1 =~ ^[0-9]+_(.*) ]]
then
  VAL1=${BASH_REMATCH[1]}
fi
</code>```

This assumes your numbers are always followed by an underscore.  If you want to avoid this assumption, you could use :

```<code>if
  [[ $VAL1 =~ ^[0-9]+_?(.*) ]]
then
  VAL1=${BASH_REMATCH[1]}
fi
</code>```

Bash regex matching works as a test (the [[ =~ ]] expression returns 0 if there is a match), and sub-expressions (defined in the matching string by using parentheses around the areas of interest) are available as elements in array BASH_REMATCH, starting at index 1.  Extended regular expressions are used.

In case anyone wonders, no double quoting is required anywhere in the above.  The [[ ]] is special shell syntax (not a command with arguments like the [/test command), no word splitting is performed inside.  The assignment also does not perform word splitting.

Body:
I have one variable which has values like this

VAL1="59809_RH_EA_TEST_1_P1_Q"

or

VAL1="89292-RH_EA_TEST_1_P1_Q"

How can I get only RH_EA_TEST_1_P1_Q using sed or any other bash command

Body:
One way is to use Bash regex matching.

VAL1="59809_RH_EA_TEST_1_P1_Q"

if
  [[ $VAL1 =~ ^[0-9]+_(.*) ]]
then
  VAL1=${BASH_REMATCH[1]}
fi

This assumes your numbers are always followed by an underscore.  If you want to avoid this assumption, you could use :

if
  [[ $VAL1 =~ ^[0-9]+_?(.*) ]]
then
  VAL1=${BASH_REMATCH[1]}
fi

Bash regex matching works as a test (the [[ =~ ]] expression returns 0 if there is a match), and sub-expressions (defined in the matching string by using parentheses around the areas of interest) are available as elements in array BASH_REMATCH, starting at index 1.  Extended regular expressions are used.

In case anyone wonders, no double quoting is required anywhere in the above.  The [[ ]] is special shell syntax (not a command with arguments like the [/test command), no word splitting is performed inside.  The assignment also does not perform word splitting.


来源: stackexchange

答:
Based on your code the dates are just characters.

Try converting them to Dates:

```<code>plot(as.Date(d$Date), d$Entry.Count)
</code>```

Quite simple in your case as the "%Y-%m-%d" format is the default for as.Date. See strptime for more general options.

ContentLicense: CC BY-SA 2.5

Title: Plot with dates as X axis in R

Body:
I maintain my journal electronically and I'm trying to get an idea of how consistent I've been with my journal writing over the last few months. I have the following data file, which shows how many journal entries (Entry Count) and words (Word Count) I recorded over the preceding 30-day period.

Date    Entry Count Word Count
2010-08-25  22  4205
2010-08-26  21  4012
2010-08-27  20  3865
2010-08-28  20  4062
2010-08-29  19  3938
2010-08-30  18  3759
2010-08-31  17  3564
2010-09-01  17  3564
2010-09-02  16  3444
2010-09-03  17  3647
2010-09-04  17  3617
2010-09-05  16  3390
2010-09-06  15  3251
2010-09-07  15  3186
2010-09-08  15  3186
2010-09-09  16  3414
2010-09-10  15  3228
2010-09-11  14  3006
2010-09-12  13  2769
2010-09-13  13  2781
2010-09-14  12  2637
2010-09-15  13  2774
2010-09-16  13  2808
2010-09-17  12  2732
2010-09-18  12  2664
2010-09-19  13  2931
2010-09-20  13  2751
2010-09-21  13  2710
2010-09-22  14  2950
2010-09-23  14  2834
2010-09-24  14  2834
2010-09-25  14  2834
2010-09-26  14  2834
2010-09-27  14  2834
2010-09-28  14  2543
2010-09-29  14  2543
2010-09-30  15  2884
2010-10-01  16  3105
2010-10-02  16  3105
2010-10-03  16  3105
2010-10-04  15  2902
2010-10-05  14  2805
2010-10-06  14  2805
2010-10-07  14  2805
2010-10-08  14  2812
2010-10-09  15  2895
2010-10-10  14  2667
2010-10-11  15  2876
2010-10-12  16  2938
2010-10-13  17  3112
2010-10-14  16  2894
2010-10-15  16  2894
2010-10-16  16  2923
2010-10-17  15  2722
2010-10-18  15  2722
2010-10-19  14  2544
2010-10-20  13  2277
2010-10-21  13  2329
2010-10-22  12  2132
2010-10-23  11  1892
2010-10-24  10  1764
2010-10-25  10  1764
2010-10-26  10  1764
2010-10-27  10  1764
2010-10-28  10  1764
2010-10-29  9   1670
2010-10-30  10  1969
2010-10-31  10  1709
2010-11-01  10  1624
2010-11-02  11  1677
2010-11-03  11  1677
2010-11-04  11  1677
2010-11-05  11  1677
2010-11-06  12  1786
2010-11-07  12  1786
2010-11-08  11  1529
2010-11-09  10  1446
2010-11-10  11  1682
2010-11-11  11  1540
2010-11-12  11  1673
2010-11-13  11  1765
2010-11-14  12  1924
2010-11-15  13  2276
2010-11-16  12  2110
2010-11-17  13  2524
2010-11-18  14  2615
2010-11-19  14  2615
2010-11-20  15  2706
2010-11-21  14  2549
2010-11-22  15  2647
2010-11-23  16  2874
2010-11-24  16  2874
2010-11-25  16  2874
2010-11-26  17  3249
2010-11-27  18  3421
2010-11-28  18  3421
2010-11-29  19  3647

I'm trying to plot this data with R to get a graphical representation of my journal-writing consistency. I load it into R with the following command.

d <- read.table("journal.txt", header=T, sep="\t")

I can then graph the data with the following command.

plot(seq(from=1, to=length(d$Entry.Count), by=1), d$Entry.Count, type="o", ylim=c(0, max(d$Entry.Count)))

However, in this plot the X axis is just a number, not a date. I tried adjusting the command to show dates on the X axis like this.

plot(d$Date, d$Entry.Count, type="o", ylim=c(0, max(d$Entry.Count)))

However, not only does the plot look strange, but the labels on the X axis are not very helpful. What is the best way to plot this data so that I can clearly associate dates with points on the plotted curve?

Body:
Based on your code the dates are just characters.

Try converting them to Dates:

plot(as.Date(d$Date), d$Entry.Count)

Quite simple in your case as the "%Y-%m-%d" format is the default for as.Date. See strptime for more general options.


问:
Aligning SCNText with SCNBox in iOS SceneKit with boundingBox?
REVISED PROBLEM:

I don't understand why the white node is centered when it's a box or sphere but not when it's text.  You can comment/uncomment the whiteGeometry variable to see how each different geometry is displayed.  I was originally thinking that I had to manually center the text by determining the width of the box and the text and calculating the position of the text.  Do I need to do that?  Why is the text behaving differently?

```<code>import SceneKit
import PlaygroundSupport

let scene = SCNScene()
let sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
sceneView.scene = scene
sceneView.backgroundColor = .darkGray
sceneView.autoenablesDefaultLighting = true
sceneView.allowsCameraControl = true
PlaygroundPage.current.liveView = sceneView

// Camera
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
cameraNode.position = SCNVector3(x: 0, y: 0, z: 25)
sceneView.pointOfView = cameraNode

let blackGeometry = SCNBox(width: 10.0, height: 10.0, length: 10.0, chamferRadius: 0)
blackGeometry.firstMaterial?.diffuse.contents = UIColor.black
print("blackGeometry min=\(blackGeometry.boundingBox.min)")
print("blackGeometry max=\(blackGeometry.boundingBox.max)")
let blackNode = SCNNode(geometry: blackGeometry)
blackNode.position = SCNVector3(x: 0, y: 0, z: 0)
scene.rootNode.addChildNode(blackNode)

// let whiteGeometry = SCNBox(width: 3.0, height: 3.0, length: 3.0, chamferRadius: 0)
let whiteGeometry = SCNText(string: "L", extrusionDepth: 0)
whiteGeometry.alignmentMode =  kCAAlignmentLeft
whiteGeometry.font = UIFont.systemFont(ofSize: 8.0)
// let whiteGeometry = SCNSphere(radius: 3.0)
whiteGeometry.firstMaterial?.diffuse.contents = UIColor.white
print("whiteGeometry min=\(whiteGeometry.boundingBox.min)")
print("whiteGeometry max=\(whiteGeometry.boundingBox.max)")
let whiteNode = SCNNode(geometry: whiteGeometry)

let boxWidth = blackGeometry.boundingBox.max.x - blackGeometry.boundingBox.min.x
let boxHeight = blackGeometry.boundingBox.max.y - blackGeometry.boundingBox.min.y
print("boxWidth=\(boxWidth)")
print("boxHeight=\(boxHeight)")

let txtWidth = whiteGeometry.boundingBox.max.x - whiteGeometry.boundingBox.min.x
let txtHeight = whiteGeometry.boundingBox.max.y - whiteGeometry.boundingBox.min.y
print("txtWidth=\(txtWidth)")
print("txtHeight=\(txtHeight)")

whiteNode.position = SCNVector3(x: -5.0, y: -5.0, z: 10)
scene.rootNode.addChildNode(whiteNode)
//blackNode.addChildNode(whiteNode)

print("done")
</code>```

ORIGINAL PROBLEM (OLD):

Let's say I have two SCNBox nodes (I'm simplifying this to make it clear BUT the solution must work for other geometries).  A large black box and a small white box.  I want to center the white box in front of the black box.

To do this, I need to determine the width and height of the two nodes.  Remember that the node could be something other than a box like a sphere or text.  From what I can tell, the only way to determine width/height is via the boundingBox property on the geometry.  It has a min and max value that is NOT clearly and fully described in Apple's reference manual.  To get the height, it seems like I would calculate it based on boundingBox.max.y and boundingBox.min.y.  So looking at the example below of a 10x10x10 box, I can't see how I can get 10.0 as the height because max.y 5.20507812

e.g.

```<code>let box = SCNBox(width: 10.0, height: 10.0, length: 10.0, chamferRadius: 0)
print("box min=\(box.boundingBox.min)")
print("box max=\(box.boundingBox.max)")
</code>```

yields:

```<code>box min=SCNVector3(x: -5.0, y: -5.0, z: -5.0)
box max=SCNVector3(x: 5.0, y: 5.20507812, z: 5.0)
</code>```

Why is max.y=5.20507812?  How should I determine the height/width?

See also: SCNBoundingVolume

答:
I think I understand now.

It looks like you're trying to put some text in front of an object, with the text centered on the object relative to the camera. And this question isn't about bounding boxes per se. Right?

You see different behavior with the white geometry being a sphere or SCNText because SCNText's uses a different origin convention than the other concrete SCNGeometry classes. Other geometries put the origin at the center. SCNText puts it at the lower left of the text. If I remember correctly, "lower" means the bottom of the font (lowest descender), not the baseline.

So you'll need to compute the text's bounding box, and account for that when you position the text node, to get it centered. You don't need to do that for the other geometry types. If the covered object or the camera is moving, you'll need to compute the ray from the camera to the covered object in the render loop, and update the text's position.

Swift Scenekit - Centering SCNText - the getBoundingBoxMin:Max issue is relevant.

If you just want overlay text, you might find it easier to put the text in an SKScene overlay. An example of that is at https://github.com/halmueller/ImmersiveInterfaces/tree/master/Tracking%20Overlay (warning, bit rot may have set in, I haven't tried that code in a while).

ContentLicense: CC BY-SA 3.0

Body:
REVISED PROBLEM:

I don't understand why the white node is centered when it's a box or sphere but not when it's text.  You can comment/uncomment the whiteGeometry variable to see how each different geometry is displayed.  I was originally thinking that I had to manually center the text by determining the width of the box and the text and calculating the position of the text.  Do I need to do that?  Why is the text behaving differently?

import SceneKit
import PlaygroundSupport

let scene = SCNScene()
let sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
sceneView.scene = scene
sceneView.backgroundColor = .darkGray
sceneView.autoenablesDefaultLighting = true
sceneView.allowsCameraControl = true
PlaygroundPage.current.liveView = sceneView

// Camera
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
cameraNode.position = SCNVector3(x: 0, y: 0, z: 25)
sceneView.pointOfView = cameraNode

let blackGeometry = SCNBox(width: 10.0, height: 10.0, length: 10.0, chamferRadius: 0)
blackGeometry.firstMaterial?.diffuse.contents = UIColor.black
print("blackGeometry min=\(blackGeometry.boundingBox.min)")
print("blackGeometry max=\(blackGeometry.boundingBox.max)")
let blackNode = SCNNode(geometry: blackGeometry)
blackNode.position = SCNVector3(x: 0, y: 0, z: 0)
scene.rootNode.addChildNode(blackNode)

// let whiteGeometry = SCNBox(width: 3.0, height: 3.0, length: 3.0, chamferRadius: 0)
let whiteGeometry = SCNText(string: "L", extrusionDepth: 0)
whiteGeometry.alignmentMode =  kCAAlignmentLeft
whiteGeometry.font = UIFont.systemFont(ofSize: 8.0)
// let whiteGeometry = SCNSphere(radius: 3.0)
whiteGeometry.firstMaterial?.diffuse.contents = UIColor.white
print("whiteGeometry min=\(whiteGeometry.boundingBox.min)")
print("whiteGeometry max=\(whiteGeometry.boundingBox.max)")
let whiteNode = SCNNode(geometry: whiteGeometry)

let boxWidth = blackGeometry.boundingBox.max.x - blackGeometry.boundingBox.min.x
let boxHeight = blackGeometry.boundingBox.max.y - blackGeometry.boundingBox.min.y
print("boxWidth=\(boxWidth)")
print("boxHeight=\(boxHeight)")

let txtWidth = whiteGeometry.boundingBox.max.x - whiteGeometry.boundingBox.min.x
let txtHeight = whiteGeometry.boundingBox.max.y - whiteGeometry.boundingBox.min.y
print("txtWidth=\(txtWidth)")
print("txtHeight=\(txtHeight)")

whiteNode.position = SCNVector3(x: -5.0, y: -5.0, z: 10)
scene.rootNode.addChildNode(whiteNode)
//blackNode.addChildNode(whiteNode)

print("done")

ORIGINAL PROBLEM (OLD):

Let's say I have two SCNBox nodes (I'm simplifying this to make it clear BUT the solution must work for other geometries).  A large black box and a small white box.  I want to center the white box in front of the black box.

To do this, I need to determine the width and height of the two nodes.  Remember that the node could be something other than a box like a sphere or text.  From what I can tell, the only way to determine width/height is via the boundingBox property on the geometry.  It has a min and max value that is NOT clearly and fully described in Apple's reference manual.  To get the height, it seems like I would calculate it based on boundingBox.max.y and boundingBox.min.y.  So looking at the example below of a 10x10x10 box, I can't see how I can get 10.0 as the height because max.y 5.20507812

e.g.

let box = SCNBox(width: 10.0, height: 10.0, length: 10.0, chamferRadius: 0)
print("box min=\(box.boundingBox.min)")
print("box max=\(box.boundingBox.max)")

yields:

box min=SCNVector3(x: -5.0, y: -5.0, z: -5.0)
box max=SCNVector3(x: 5.0, y: 5.20507812, z: 5.0)

Why is max.y=5.20507812?  How should I determine the height/width?

See also: SCNBoundingVolume


问:
WPF troubles hooking CollectionChanged events
I have a datagrid where I need to calculate the total of the Price column of a nested datagrid, like so:

Image

I'm trying to follow this example so that my Items observable collection for each Person object gets notified on changes. The difference is that I'm implementing it inside a class, not View Model.

```<code>public class Person : NotifyObject
    {
        private ObservableCollection<Item> _items;
        public ObservableCollection<Item> Items
        {
            get { return _items; }
            set { _items = value; OnPropertyChanged("Items"); }
        }
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }
        public double Total
        {
            get { return Items.Sum(i => i.Price); }
            set { OnPropertyChanged("Total"); }
        }

        public Person()
        {
            Console.WriteLine("0001 Constructor");
            this.Items = new ObservableCollection<Item>();
            this.Items.CollectionChanged += Items_CollectionChanged;
            this.Items.Add(new Item());
        }
        private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Console.WriteLine("0002 CollectionChanged");
            if (e.NewItems != null)
                foreach (Item item in e.NewItems)
                    item.PropertyChanged += Items_PropertyChanged;

            if (e.OldItems != null)
                foreach (Item item in e.OldItems)
                    item.PropertyChanged -= Items_PropertyChanged;
        }

        private void Items_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine("0003 PropertyChanged");
            this.Total = Items.Sum(i => i.Price);
        }
    }
</code>```

The code inside the constructor doesn't hook events when a new Item is initialized  or an existing one has been edited. Therefore, the Items_PropertyChanged event never fires. I only can refresh the entire list manually. What am I doing wrong here?

Or maybe there's a different approach to calculate the total for each Person's purchase list?

Below is the entire code if anyone cares too look at it.

XAML

```<code><Window x:Class="collection_changed_2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:collection_changed_2"
        mc:Ignorable="d"
        Title="MainWindow" SizeToContent="Height" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition />
        </Grid.RowDefinitions>
        <DataGrid x:Name="DataGrid1"
                  Grid.Row="0"
                  ItemsSource="{Binding DataCollection}"
                  SelectedItem="{Binding DataCollectionSelectedItem}"
                  AutoGenerateColumns="False"
                  CanUserAddRows="false" >
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="2*"/>
                <DataGridTemplateColumn Header="Item/Price" Width="3*">
                    <DataGridTemplateColumn.CellTemplate >
                        <DataTemplate>
                            <DataGrid x:Name="DataGridItem"
                                      ItemsSource="{Binding Items}"
                                      SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ItemsSelectedItem}"
                                      Background="Transparent"
                                      HeadersVisibility="None"
                                      AutoGenerateColumns="False"
                                      CanUserAddRows="false" >
                                <DataGrid.Columns>
                                    <DataGridTextColumn Binding="{Binding ItemName}" Width="*"/>
                                    <DataGridTextColumn Binding="{Binding Price}" Width="50"/>
                                    <DataGridTemplateColumn Header="Button" Width="Auto">
                                        <DataGridTemplateColumn.CellTemplate>
                                            <DataTemplate>
                                                <StackPanel>
                                                    <Button  Content="+"
                                                             Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.AddItem }"
                                                             Width="20" Height="20">
                                                    </Button>
                                                </StackPanel>
                                            </DataTemplate>
                                        </DataGridTemplateColumn.CellTemplate>
                                    </DataGridTemplateColumn>
                                </DataGrid.Columns>
                            </DataGrid>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="Total" Binding="{Binding Total, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="Auto"/>
                <DataGridTemplateColumn Header="Buttons" Width="Auto">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel VerticalAlignment="Center">
                                <Button  Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.AddPerson}" Width="20" Height="20">+</Button>
                            </StackPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
        <StackPanel Grid.Row="1" Margin="10">
            <Button  Width="150" Height="30"  Content="Refresh" Command="{Binding Refresh}" />
        </StackPanel>
    </Grid>
</Window>
</code>```

C#

```<code>using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;

namespace collection_changed_2
{
    public class Item : NotifyObject
    {
        private string _itemName;
        public string ItemName
        {
            get { return _itemName; }
            set { _itemName = value; OnPropertyChanged("ItemName"); }
        }
        private double _price;
        public double Price
        {
            get { return _price; }
            set { _price = value; OnPropertyChanged("Price"); }
        }
    }

    public class Person : NotifyObject
    {
        private ObservableCollection<Item> _items;
        public ObservableCollection<Item> Items
        {
            get { return _items; }
            set { _items = value; OnPropertyChanged("Items"); }
        }
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }
        public double Total
        {
            get { return Items.Sum(i => i.Price); }
            set { OnPropertyChanged("Total"); }
        }

        public Person()
        {
            Console.WriteLine("0001 Constructor");
            this.Items = new ObservableCollection<Item>();
            this.Items.CollectionChanged += Items_CollectionChanged;
            this.Items.Add(new Item());
        }
        private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Console.WriteLine("0002 CollectionChanged");
            if (e.NewItems != null)
                foreach (Item item in e.NewItems)
                    item.PropertyChanged += Items_PropertyChanged;

            if (e.OldItems != null)
                foreach (Item item in e.OldItems)
                    item.PropertyChanged -= Items_PropertyChanged;
        }

        private void Items_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine("0003 PropertyChanged");
            this.Total = Items.Sum(i => i.Price);
        }
    }

    public abstract class NotifyObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

    public class RelayCommand : ICommand
    {
        private Action<object> executeDelegate;
        readonly Predicate<object> canExecuteDelegate;

        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new NullReferenceException("execute");
            executeDelegate = execute;
            canExecuteDelegate = canExecute;
        }

        public RelayCommand(Action<object> execute) : this(execute, null) { }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public bool CanExecute(object parameter)
        {
            return canExecuteDelegate == null ? true : canExecuteDelegate(parameter);
        }

        public void Execute(object parameter)
        {
            executeDelegate.Invoke(parameter);
        }
    }

    public class ViewModel : NotifyObject
    {
        public ObservableCollection<Person> DataCollection { get; set; }

        public Person DataCollectionSelectedItem { get; set; }
        public Item ItemsSelectedItem { get; set; }

        public RelayCommand AddPerson { get; private set; }
        public RelayCommand AddItem { get; private set; }
        public RelayCommand Refresh { get; private set; }

        public ViewModel()
        {
            DataCollection = new ObservableCollection<Person>
            {
                new Person() {
                    Name = "Friedrich Nietzsche",
                    Items = new ObservableCollection<Item> {
                        new Item { ItemName = "Phone", Price = 220 },
                        new Item { ItemName = "Tablet", Price = 350 },
                    }
                },
                new Person() {
                    Name = "Jean Baudrillard",
                    Items = new ObservableCollection<Item> {
                        new Item { ItemName = "Teddy Bear Deluxe", Price = 2200 },
                        new Item { ItemName = "Pokemon", Price = 100 }
                    }
                 }
            };

            AddItem = new RelayCommand(AddItemCode, null);
            AddPerson = new RelayCommand(AddPersonCode, null);
            Refresh = new RelayCommand(RefreshCode, null);
        }

        public void AddItemCode(object parameter)
        {
            var collectionIndex = DataCollection.IndexOf(DataCollectionSelectedItem);
            var itemIndex = DataCollection[collectionIndex].Items.IndexOf(ItemsSelectedItem);
            Item newItem = new Item() { ItemName = "Item_Name", Price = 100 };
            DataCollection[collectionIndex].Items.Insert(itemIndex + 1, newItem);
        }
        public void AddPersonCode(object parameter)
        {
            var collectionIndex = DataCollection.IndexOf(DataCollectionSelectedItem);
            Person newList = new Person()
            {
                Name = "New_Name",
                Items = new ObservableCollection<Item>() { new Item() { ItemName = "Item_Name", Price = 100 } }
            };
            DataCollection.Insert(collectionIndex + 1, newList);
        }
        private void RefreshCode(object parameter)
        {
            CollectionViewSource.GetDefaultView(DataCollection).Refresh();
        }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }
    }
}
</code>```

答:
I've eventually figured out what was wrong with my original code. I used this constructor:

```<code>public Person()
        {
            this.Items = new ObservableCollection<Item>();
            this.Items.CollectionChanged += Items_CollectionChanged;
            this.Items.Add(new Item());
        }
</code>```

The attached event was then effectively overwritten by this initializer:

```<code>Person newList = new Person()
            {
                Name = "New_Name",
                Items = new ObservableCollection<Item>() { new Item() { ItemName = "Item_Name", Price = 100 } }
            };
</code>```

That is why the event never fired. It wasn't there! The correct way is to use a parametric constructor:

```<code>public Person(string initName, ObservableCollection<Item> initItems)
        {
            this.Name = initName;
            this.Items = new ObservableCollection<Item>();
            this.Items.CollectionChanged += Items_CollectionChanged;
            foreach (Item item in initItems)
                this.Items.Add(item);
        }
</code>```

And then initialize it like so:

```<code>Person newList = new Person("New_Name", new ObservableCollection<Item>() { new Item() { ItemName = "Item_Name", Price = 100 } });
</code>```

And that was it. Works like a charm now. Below is the full code of the original example reworked:

```<code>using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;

namespace collection_changed_4
{
    public class Item : NotifyObject
    {
        private string _itemName;
        public string ItemName
        {
            get { return _itemName; }
            set { _itemName = value; OnPropertyChanged("ItemName"); }
        }
        private double _price;
        public double Price
        {
            get { return _price; }
            set { _price = value; OnPropertyChanged("Price"); }
        }
    }

    public class Person : NotifyObject
    {
        private ObservableCollection<Item> _items;
        public ObservableCollection<Item> Items
        {
            get { return _items; }
            set { _items = value; OnPropertyChanged("Items"); }
        }
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }
        public double Total
        {
            get { return Items.Sum(i => i.Price); }
            set { OnPropertyChanged("Total"); }
        }

        public Person(string initName, ObservableCollection<Item> initItems)
        {
            Console.WriteLine("0001 Constructor");
            this.Name = initName;
            this.Items = new ObservableCollection<Item>();
            this.Items.CollectionChanged += Items_CollectionChanged;
            foreach (Item item in initItems)
                this.Items.Add(item);
        }
        private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Console.WriteLine("0002 CollectionChanged");
            if (e.NewItems != null)
                foreach (Item item in e.NewItems)
                    item.PropertyChanged += Items_PropertyChanged;

            if (e.OldItems != null)
                foreach (Item item in e.OldItems)
                    item.PropertyChanged -= Items_PropertyChanged;
            OnPropertyChanged("Total");
        }

        private void Items_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine("0003 PropertyChanged");
            OnPropertyChanged("Total");
        }
    }

    public abstract class NotifyObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

    public class RelayCommand : ICommand
    {
        private Action<object> executeDelegate;
        readonly Predicate<object> canExecuteDelegate;

        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new NullReferenceException("execute");
            executeDelegate = execute;
            canExecuteDelegate = canExecute;
        }

        public RelayCommand(Action<object> execute) : this(execute, null) { }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public bool CanExecute(object parameter)
        {
            return canExecuteDelegate == null ? true : canExecuteDelegate(parameter);
        }

        public void Execute(object parameter)
        {
            executeDelegate.Invoke(parameter);
        }
    }

    public class ViewModel : NotifyObject
    {
        public ObservableCollection<Person> DataCollection { get; set; }

        public Person DataCollectionSelectedItem { get; set; }
        public Item ItemsSelectedItem { get; set; }

        public RelayCommand AddPerson { get; private set; }
        public RelayCommand AddItem { get; private set; }
        public RelayCommand Refresh { get; private set; }

        public ViewModel()
        {
            DataCollection = new ObservableCollection<Person>
            {
                new Person("Friedrich Nietzsche", new ObservableCollection<Item> {
                        new Item { ItemName = "Phone", Price = 220 },
                        new Item { ItemName = "Tablet", Price = 350 },
                    } ),
                new Person("Jean Baudrillard", new ObservableCollection<Item> {
                        new Item { ItemName = "Teddy Bear Deluxe", Price = 2200 },
                        new Item { ItemName = "Pokemon", Price = 100 }
                    })
            };

            AddItem = new RelayCommand(AddItemCode, null);
            AddPerson = new RelayCommand(AddPersonCode, null);
            Refresh = new RelayCommand(RefreshCode, null);
        }

        public void AddItemCode(object parameter)
        {
            var collectionIndex = DataCollection.IndexOf(DataCollectionSelectedItem);
            var itemIndex = DataCollection[collectionIndex].Items.IndexOf(ItemsSelectedItem);
            Item newItem = new Item() { ItemName = "Item_Name", Price = 100 };
            DataCollection[collectionIndex].Items.Insert(itemIndex + 1, newItem);
        }
        public void AddPersonCode(object parameter)
        {
            var collectionIndex = DataCollection.IndexOf(DataCollectionSelectedItem);
            Person newList = new Person("New_Name", new ObservableCollection<Item>() { new Item() { ItemName = "Item_Name", Price = 100 } });
            DataCollection.Insert(collectionIndex + 1, newList);
        }
        private void RefreshCode(object parameter)
        {
            CollectionViewSource.GetDefaultView(DataCollection).Refresh();
        }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }
    }
}
</code>```

Body:
I have a datagrid where I need to calculate the total of the Price column of a nested datagrid, like so:

Image

I'm trying to follow this example so that my Items observable collection for each Person object gets notified on changes. The difference is that I'm implementing it inside a class, not View Model.

public class Person : NotifyObject
    {
        private ObservableCollection<Item> _items;
        public ObservableCollection<Item> Items
        {
            get { return _items; }
            set { _items = value; OnPropertyChanged("Items"); }
        }
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }
        public double Total
        {
            get { return Items.Sum(i => i.Price); }
            set { OnPropertyChanged("Total"); }
        }

        public Person()
        {
            Console.WriteLine("0001 Constructor");
            this.Items = new ObservableCollection<Item>();
            this.Items.CollectionChanged += Items_CollectionChanged;
            this.Items.Add(new Item());
        }
        private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Console.WriteLine("0002 CollectionChanged");
            if (e.NewItems != null)
                foreach (Item item in e.NewItems)
                    item.PropertyChanged += Items_PropertyChanged;

            if (e.OldItems != null)
                foreach (Item item in e.OldItems)
                    item.PropertyChanged -= Items_PropertyChanged;
        }

        private void Items_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine("0003 PropertyChanged");
            this.Total = Items.Sum(i => i.Price);
        }
    }

The code inside the constructor doesn't hook events when a new Item is initialized  or an existing one has been edited. Therefore, the Items_PropertyChanged event never fires. I only can refresh the entire list manually. What am I doing wrong here?

Or maybe there's a different approach to calculate the total for each Person's purchase list?

Below is the entire code if anyone cares too look at it.

XAML

<Window x:Class="collection_changed_2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:collection_changed_2"
        mc:Ignorable="d"
        Title="MainWindow" SizeToContent="Height" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition />
        </Grid.RowDefinitions>
        <DataGrid x:Name="DataGrid1"
                  Grid.Row="0"
                  ItemsSource="{Binding DataCollection}"
                  SelectedItem="{Binding DataCollectionSelectedItem}"
                  AutoGenerateColumns="False"
                  CanUserAddRows="false" >
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="2*"/>
                <DataGridTemplateColumn Header="Item/Price" Width="3*">
                    <DataGridTemplateColumn.CellTemplate >
                        <DataTemplate>
                            <DataGrid x:Name="DataGridItem"
                                      ItemsSource="{Binding Items}"
                                      SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ItemsSelectedItem}"
                                      Background="Transparent"
                                      HeadersVisibility="None"
                                      AutoGenerateColumns="False"
                                      CanUserAddRows="false" >
                                <DataGrid.Columns>
                                    <DataGridTextColumn Binding="{Binding ItemName}" Width="*"/>
                                    <DataGridTextColumn Binding="{Binding Price}" Width="50"/>
                                    <DataGridTemplateColumn Header="Button" Width="Auto">
                                        <DataGridTemplateColumn.CellTemplate>
                                            <DataTemplate>
                                                <StackPanel>
                                                    <Button  Content="+"
                                                             Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.AddItem }"
                                                             Width="20" Height="20">
                                                    </Button>
                                                </StackPanel>
                                            </DataTemplate>
                                        </DataGridTemplateColumn.CellTemplate>
                                    </DataGridTemplateColumn>
                                </DataGrid.Columns>
                            </DataGrid>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="Total" Binding="{Binding Total, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="Auto"/>
                <DataGridTemplateColumn Header="Buttons" Width="Auto">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel VerticalAlignment="Center">
                                <Button  Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.AddPerson}" Width="20" Height="20">+</Button>
                            </StackPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
        <StackPanel Grid.Row="1" Margin="10">
            <Button  Width="150" Height="30"  Content="Refresh" Command="{Binding Refresh}" />
        </StackPanel>
    </Grid>
</Window>

C#

using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;

namespace collection_changed_2
{
    public class Item : NotifyObject
    {
        private string _itemName;
        public string ItemName
        {
            get { return _itemName; }
            set { _itemName = value; OnPropertyChanged("ItemName"); }
        }
        private double _price;
        public double Price
        {
            get { return _price; }
            set { _price = value; OnPropertyChanged("Price"); }
        }
    }

    public class Person : NotifyObject
    {
        private ObservableCollection<Item> _items;
        public ObservableCollection<Item> Items
        {
            get { return _items; }
            set { _items = value; OnPropertyChanged("Items"); }
        }
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }
        public double Total
        {
            get { return Items.Sum(i => i.Price); }
            set { OnPropertyChanged("Total"); }
        }

        public Person()
        {
            Console.WriteLine("0001 Constructor");
            this.Items = new ObservableCollection<Item>();
            this.Items.CollectionChanged += Items_CollectionChanged;
            this.Items.Add(new Item());
        }
        private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Console.WriteLine("0002 CollectionChanged");
            if (e.NewItems != null)
                foreach (Item item in e.NewItems)
                    item.PropertyChanged += Items_PropertyChanged;

            if (e.OldItems != null)
                foreach (Item item in e.OldItems)
                    item.PropertyChanged -= Items_PropertyChanged;
        }

        private void Items_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine("0003 PropertyChanged");
            this.Total = Items.Sum(i => i.Price);
        }
    }

    public abstract class NotifyObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

    public class RelayCommand : ICommand
    {
        private Action<object> executeDelegate;
        readonly Predicate<object> canExecuteDelegate;

        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new NullReferenceException("execute");
            executeDelegate = execute;
            canExecuteDelegate = canExecute;
        }

        public RelayCommand(Action<object> execute) : this(execute, null) { }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public bool CanExecute(object parameter)
        {
            return canExecuteDelegate == null ? true : canExecuteDelegate(parameter);
        }

        public void Execute(object parameter)
        {
            executeDelegate.Invoke(parameter);
        }
    }

    public class ViewModel : NotifyObject
    {
        public ObservableCollection<Person> DataCollection { get; set; }

        public Person DataCollectionSelectedItem { get; set; }
        public Item ItemsSelectedItem { get; set; }

        public RelayCommand AddPerson { get; private set; }
        public RelayCommand AddItem { get; private set; }
        public RelayCommand Refresh { get; private set; }

        public ViewModel()
        {
            DataCollection = new ObservableCollection<Person>
            {
                new Person() {
                    Name = "Friedrich Nietzsche",
                    Items = new ObservableCollection<Item> {
                        new Item { ItemName = "Phone", Price = 220 },
                        new Item { ItemName = "Tablet", Price = 350 },
                    }
                },
                new Person() {
                    Name = "Jean Baudrillard",
                    Items = new ObservableCollection<Item> {
                        new Item { ItemName = "Teddy Bear Deluxe", Price = 2200 },
                        new Item { ItemName = "Pokemon", Price = 100 }
                    }
                 }
            };

            AddItem = new RelayCommand(AddItemCode, null);
            AddPerson = new RelayCommand(AddPersonCode, null);
            Refresh = new RelayCommand(RefreshCode, null);
        }

        public void AddItemCode(object parameter)
        {
            var collectionIndex = DataCollection.IndexOf(DataCollectionSelectedItem);
            var itemIndex = DataCollection[collectionIndex].Items.IndexOf(ItemsSelectedItem);
            Item newItem = new Item() { ItemName = "Item_Name", Price = 100 };
            DataCollection[collectionIndex].Items.Insert(itemIndex + 1, newItem);
        }
        public void AddPersonCode(object parameter)
        {
            var collectionIndex = DataCollection.IndexOf(DataCollectionSelectedItem);
            Person newList = new Person()
            {
                Name = "New_Name",
                Items = new ObservableCollection<Item>() { new Item() { ItemName = "Item_Name", Price = 100 } }
            };
            DataCollection.Insert(collectionIndex + 1, newList);
        }
        private void RefreshCode(object parameter)
        {
            CollectionViewSource.GetDefaultView(DataCollection).Refresh();
        }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }
    }
}

Body:
I've eventually figured out what was wrong with my original code. I used this constructor:

public Person()
        {
            this.Items = new ObservableCollection<Item>();
            this.Items.CollectionChanged += Items_CollectionChanged;
            this.Items.Add(new Item());
        }

The attached event was then effectively overwritten by this initializer:

Person newList = new Person()
            {
                Name = "New_Name",
                Items = new ObservableCollection<Item>() { new Item() { ItemName = "Item_Name", Price = 100 } }
            };

That is why the event never fired. It wasn't there! The correct way is to use a parametric constructor:

public Person(string initName, ObservableCollection<Item> initItems)
        {
            this.Name = initName;
            this.Items = new ObservableCollection<Item>();
            this.Items.CollectionChanged += Items_CollectionChanged;
            foreach (Item item in initItems)
                this.Items.Add(item);
        }

And then initialize it like so:

Person newList = new Person("New_Name", new ObservableCollection<Item>() { new Item() { ItemName = "Item_Name", Price = 100 } });

And that was it. Works like a charm now. Below is the full code of the original example reworked:

using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;

namespace collection_changed_4
{
    public class Item : NotifyObject
    {
        private string _itemName;
        public string ItemName
        {
            get { return _itemName; }
            set { _itemName = value; OnPropertyChanged("ItemName"); }
        }
        private double _price;
        public double Price
        {
            get { return _price; }
            set { _price = value; OnPropertyChanged("Price"); }
        }
    }

    public class Person : NotifyObject
    {
        private ObservableCollection<Item> _items;
        public ObservableCollection<Item> Items
        {
            get { return _items; }
            set { _items = value; OnPropertyChanged("Items"); }
        }
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }
        public double Total
        {
            get { return Items.Sum(i => i.Price); }
            set { OnPropertyChanged("Total"); }
        }

        public Person(string initName, ObservableCollection<Item> initItems)
        {
            Console.WriteLine("0001 Constructor");
            this.Name = initName;
            this.Items = new ObservableCollection<Item>();
            this.Items.CollectionChanged += Items_CollectionChanged;
            foreach (Item item in initItems)
                this.Items.Add(item);
        }
        private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            Console.WriteLine("0002 CollectionChanged");
            if (e.NewItems != null)
                foreach (Item item in e.NewItems)
                    item.PropertyChanged += Items_PropertyChanged;

            if (e.OldItems != null)
                foreach (Item item in e.OldItems)
                    item.PropertyChanged -= Items_PropertyChanged;
            OnPropertyChanged("Total");
        }

        private void Items_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine("0003 PropertyChanged");
            OnPropertyChanged("Total");
        }
    }

    public abstract class NotifyObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

    public class RelayCommand : ICommand
    {
        private Action<object> executeDelegate;
        readonly Predicate<object> canExecuteDelegate;

        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new NullReferenceException("execute");
            executeDelegate = execute;
            canExecuteDelegate = canExecute;
        }

        public RelayCommand(Action<object> execute) : this(execute, null) { }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public bool CanExecute(object parameter)
        {
            return canExecuteDelegate == null ? true : canExecuteDelegate(parameter);
        }

        public void Execute(object parameter)
        {
            executeDelegate.Invoke(parameter);
        }
    }

    public class ViewModel : NotifyObject
    {
        public ObservableCollection<Person> DataCollection { get; set; }

        public Person DataCollectionSelectedItem { get; set; }
        public Item ItemsSelectedItem { get; set; }

        public RelayCommand AddPerson { get; private set; }
        public RelayCommand AddItem { get; private set; }
        public RelayCommand Refresh { get; private set; }

        public ViewModel()
        {
            DataCollection = new ObservableCollection<Person>
            {
                new Person("Friedrich Nietzsche", new ObservableCollection<Item> {
                        new Item { ItemName = "Phone", Price = 220 },
                        new Item { ItemName = "Tablet", Price = 350 },
                    } ),
                new Person("Jean Baudrillard", new ObservableCollection<Item> {
                        new Item { ItemName = "Teddy Bear Deluxe", Price = 2200 },
                        new Item { ItemName = "Pokemon", Price = 100 }
                    })
            };

            AddItem = new RelayCommand(AddItemCode, null);
            AddPerson = new RelayCommand(AddPersonCode, null);
            Refresh = new RelayCommand(RefreshCode, null);
        }

        public void AddItemCode(object parameter)
        {
            var collectionIndex = DataCollection.IndexOf(DataCollectionSelectedItem);
            var itemIndex = DataCollection[collectionIndex].Items.IndexOf(ItemsSelectedItem);
            Item newItem = new Item() { ItemName = "Item_Name", Price = 100 };
            DataCollection[collectionIndex].Items.Insert(itemIndex + 1, newItem);
        }
        public void AddPersonCode(object parameter)
        {
            var collectionIndex = DataCollection.IndexOf(DataCollectionSelectedItem);
            Person newList = new Person("New_Name", new ObservableCollection<Item>() { new Item() { ItemName = "Item_Name", Price = 100 } });
            DataCollection.Insert(collectionIndex + 1, newList);
        }
        private void RefreshCode(object parameter)
        {
            CollectionViewSource.GetDefaultView(DataCollection).Refresh();
        }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel();
        }
    }
}


问:
Creating a custom Table Model to provide data from ArrayList
I'm trying create a JTable that creates the table based on information from an ArrayList.  The ArrayList is filled with information that the user enters in the GUI.  Every time the user presses a JButton it should add a new row of data to the table.

After googling it seems that the best way to do this is to create a custom table model.  I cannot find a decent tutorial on how to do this.  I've looked at the official documentation, and a few random sites and other postings.  Hopefully one of you can point me in the right direction.

Here's a picture of my current GUI.  The JTable should populate the center region:

And here is some of my code:

```<code> class dataModel extends AbstractTableModel
{
    private String[] columnName = {"Emp Num", "Base Pay", "Hours Worked", "Pay Amt"};

    public int getColumnCount()
    {
        return 4;
    }

    public int getRowCount()
    {
        return empData.size();
    }

    public Object getValueAt(int row, int col)
    {
        return new Integer(row*col);
    }
}
</code>```

The class that occurs on button click.

```<code>class listener implements ActionListener
{
    @SuppressWarnings("unchecked")
    public void actionPerformed(ActionEvent e)
    {
        ArrayList empData = new ArrayList();

        int empNum = 0;
        double hourlyRate = 0;
        double hoursWorked = 0;
        try
        {
            empNum = Integer.parseInt(empNumField.getText());
        }
        catch(NumberFormatException event)
        {
            JOptionPane.showMessageDialog(null, "Invalid entry.\n\nPlease enter a number for the Employee ID.", "Error", JOptionPane.WARNING_MESSAGE);
            return;
        }
        try
        {
            hourlyRate = Double.parseDouble(basePayField.getText());
        }
        catch(NumberFormatException event)
        {
            JOptionPane.showMessageDialog(null, "Invalid entry.\n\nPlease enter a number for the Hourly Pay Rate.", "Error", JOptionPane.WARNING_MESSAGE);
            return;
        }
        try
        {
            hoursWorked = Double.parseDouble(hrsField.getText());
        }
        catch(NumberFormatException event)
        {
            JOptionPane.showMessageDialog(null, "Invalid entry.\n\nPlease enter a number for the Hours Worked.", "Error", JOptionPane.WARNING_MESSAGE);
            return;
        }

        double payAMT = calculatePay(hourlyRate, hoursWorked);

        empData.add(empNum);
        empData.add(hourlyRate);
        empData.add(hoursWorked);
        empData.add(payAMT);

    }
</code>```

答:
JTable that creates the table based on information from an ArrayList.

Every time the user presses a JButton it should add a new row of data to the table.

So your real requirement is to get data from some text fields and add the data to a table.

So there is no need to use an ArrayList to do this.

You can use the DefaultTableModel for this. The DefaultTableModel supports an addRow(...) method. Using this method you can add a Vector or an Array containing the data from the 4 text fields.

So the only real change to your code would be:

```<code>//ArrayList empData = new ArrayList();
Vector empData = new Vector();
</code>```

and then after you add all the data to the Vector you need to add the Vector to the DefaultTableModel:

```<code>empData.add(payAMT);
model.addRow( empData );
</code>```

So of course you need to have created an empty DefaultTableModel with just the columns names first and your listener would need access to this model.

it seems that the best way to do this is to create a custom table model. I cannot find a decent tutorial on how to do this

Another option is to create a custom TableModel that contains Employee objects. In this case you could use an ArrayList to hold the individual Employee objects. For an example of creating a TableModel for this approach check out Row Table Model.

Body:
I'm trying create a JTable that creates the table based on information from an ArrayList.  The ArrayList is filled with information that the user enters in the GUI.  Every time the user presses a JButton it should add a new row of data to the table.

After googling it seems that the best way to do this is to create a custom table model.  I cannot find a decent tutorial on how to do this.  I've looked at the official documentation, and a few random sites and other postings.  Hopefully one of you can point me in the right direction.

Here's a picture of my current GUI.  The JTable should populate the center region:

And here is some of my code:

 class dataModel extends AbstractTableModel
{
    private String[] columnName = {"Emp Num", "Base Pay", "Hours Worked", "Pay Amt"};

    public int getColumnCount()
    {
        return 4;
    }

    public int getRowCount()
    {
        return empData.size();
    }

    public Object getValueAt(int row, int col)
    {
        return new Integer(row*col);
    }
}

The class that occurs on button click.

class listener implements ActionListener
{
    @SuppressWarnings("unchecked")
    public void actionPerformed(ActionEvent e)
    {
        ArrayList empData = new ArrayList();

        int empNum = 0;
        double hourlyRate = 0;
        double hoursWorked = 0;
        try
        {
            empNum = Integer.parseInt(empNumField.getText());
        }
        catch(NumberFormatException event)
        {
            JOptionPane.showMessageDialog(null, "Invalid entry.\n\nPlease enter a number for the Employee ID.", "Error", JOptionPane.WARNING_MESSAGE);
            return;
        }
        try
        {
            hourlyRate = Double.parseDouble(basePayField.getText());
        }
        catch(NumberFormatException event)
        {
            JOptionPane.showMessageDialog(null, "Invalid entry.\n\nPlease enter a number for the Hourly Pay Rate.", "Error", JOptionPane.WARNING_MESSAGE);
            return;
        }
        try
        {
            hoursWorked = Double.parseDouble(hrsField.getText());
        }
        catch(NumberFormatException event)
        {
            JOptionPane.showMessageDialog(null, "Invalid entry.\n\nPlease enter a number for the Hours Worked.", "Error", JOptionPane.WARNING_MESSAGE);
            return;
        }

        double payAMT = calculatePay(hourlyRate, hoursWorked);

        empData.add(empNum);
        empData.add(hourlyRate);
        empData.add(hoursWorked);
        empData.add(payAMT);

    }

Body:
JTable that creates the table based on information from an ArrayList.

Every time the user presses a JButton it should add a new row of data to the table.

So your real requirement is to get data from some text fields and add the data to a table.

So there is no need to use an ArrayList to do this.

You can use the DefaultTableModel for this. The DefaultTableModel supports an addRow(...) method. Using this method you can add a Vector or an Array containing the data from the 4 text fields.

So the only real change to your code would be:

//ArrayList empData = new ArrayList();
Vector empData = new Vector();

and then after you add all the data to the Vector you need to add the Vector to the DefaultTableModel:

empData.add(payAMT);
model.addRow( empData );

So of course you need to have created an empty DefaultTableModel with just the columns names first and your listener would need access to this model.

it seems that the best way to do this is to create a custom table model. I cannot find a decent tutorial on how to do this

Another option is to create a custom TableModel that contains Employee objects. In this case you could use an ArrayList to hold the individual Employee objects. For an example of creating a TableModel for this approach check out Row Table Model.


问:
Installation Tools for ASP.Net C# application
We have developed an ASP.Net/C#/SQL Server application and use SetupBuilder (from LinderSoft) and MSI for software installation purposes.

We are having all sorts trouble with the MSI component - in that installations regularly fail and we appear to have limited control over the MSI interface/process.

Are there any installation tools that give us more control over the MSI install process and can anyone recommend a better set of tools for software deployment purposes?

答:
Most asp.net applications i've ever used have had a partly manual installation process, eg they ask you to create a sql server database and user, then copy the application in and update the web.config to reflect the sql user, then create the IIS application manually, and any further installation (eg creating the db schema) is handled automatically by the app the first time you use it.

It's always seemed acceptable to me, so long as everything is documented well i've been happy to accept it, worth considering?

I guess it depends upon the expected technical skills of your target user base...


问:
Stanford CoreNLP using Chinese on Spark error : Unknown language UniversalChinese
I'm using Stanford CoreNLP to do POS tagging for Chinese corpus.
Now I want to use it on Spark but I get this error.</p>

```<code>java.io.IOException: java.lang.RuntimeException: Unknown language UniversalChinese
at org.apache.spark.util.Utils$.tryOrIOException(Utils.scala:1163)
at org.apache.spark.rdd.ParallelCollectionPartition.readObject(ParallelCollectionRDD.scala:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1058)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1909)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1808)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2018)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1942)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1808)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
at org.apache.spark.serializer.JavaDeserializationStream.readObject(JavaSerializer.scala:72)
at org.apache.spark.serializer.JavaSerializerInstance.deserialize(JavaSerializer.scala:98)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:194)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
</code>```

答:
Could you provide more details about how you are calling Stanford CoreNLP?

My first guess is that there is a mismatch between the code jar you are using and the model.  What jars are you using for the code and for the models?

If that isn't the issue if you could describe the code you are using some more with some examples I can look into it more.  Are you using the standard Spark set up for Stanford CoreNLP?

This one: https://github.com/databricks/spark-corenlp

Body:
I'm using Stanford CoreNLP to do POS tagging for Chinese corpus.
Now I want to use it on Spark but I get this error.

java.io.IOException: java.lang.RuntimeException: Unknown language UniversalChinese
at org.apache.spark.util.Utils$.tryOrIOException(Utils.scala:1163)
at org.apache.spark.rdd.ParallelCollectionPartition.readObject(ParallelCollectionRDD.scala:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1058)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1909)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1808)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2018)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1942)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1808)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1353)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:373)
at org.apache.spark.serializer.JavaDeserializationStream.readObject(JavaSerializer.scala:72)
at org.apache.spark.serializer.JavaSerializerInstance.deserialize(JavaSerializer.scala:98)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:194)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)


问:
Get User online/offline state
I have chat app where i need to develop user online state and for this i am calling API in every 15 seconds on server, which will return all logged in users and their online state in 0(Offline) and 1(Online).

I need to show whether user is online or offline (leaves app not logged out) while chatting.I have 1 array list which shows when app is launch with all logged in user id and their details including their online state and i created second API which return users online state in JSON.I have following option to achieve users online state

Replace existing array list item:-I am getting User ID and their online state in JSON but i need to run loop in every 15 second which replace values in existing arraylist

Store JSON in someway where i can easily find user id and its state:- If i store JSON in array list i need to  run loop to find ID and its state which i dont want to,So which is best way to store JSON so i can easily get user state by its User ID.

Here is how i am getting JSON

```<code>protected List<WrapperClass> doInBackground(Void... params) {
        userSession=new UserSession(context,"Elaxer");
        UserState_Update=new ArrayList<>();

            String data = null;
            try {
                String ID=userSession.getUserID(); //Getting Value from shared pref
                data = URLEncoder.encode("User_ID", "UTF-8") + "=" + URLEncoder.encode(ID, "UTF-8");
                Log.d(TAG,"Login ID "+ ID);
                Log.d(TAG,"DO IN BACKGROUND START ");
                URL url=new URL(URL_Path_NearBy);
                connection= (HttpURLConnection) url.openConnection();
                Log.d(TAG,connection.toString());
                connection.setRequestMethod("POST");
                connection.setDoInput(true);
                connection.setDoOutput(true);

                //For POST Only - Begin
                OutputStream os = connection.getOutputStream();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
                writer.write(data);
                writer.flush();
                writer.close();
                os.close();
                connection.connect();

                InputStream inputStream=connection.getInputStream();
                reader=new BufferedReader(new InputStreamReader(inputStream));
                Log.d(TAG,"GET INPUT STREAM AND PUUTING INTO READER");
                String line;
                StringBuffer stringBuffer=new StringBuffer();
                while ((line=reader.readLine())!=null){
                    stringBuffer.append(line);

                }
                String completeJSON=stringBuffer.toString();
                Log.d(TAG,"JSON ARRAY START");

                JSONObject parentArray=new JSONObject(completeJSON);
                JSONArray jsonArray=parentArray.getJSONArray("uData");

                String LastSeen;
                int LoginStatus,User_ID;
                int Rec_Online_Status;

                for (int i = 0; i <jsonArray.length() ; i++) {
                    JSONObject childObject=jsonArray.getJSONObject(i);

                    LastSeen=childObject.getString("lastseen") ;
                    LoginStatus=childObject.getInt("login_status") ;
                    User_ID=childObject.getInt("User_ID");
                    String UseID= String.valueOf(User_ID);
                    Log.d(TAG,"JSON Values "+LastSeen+" "+LoginStatus+" "+User_ID);

                    WrapperClass wrapperClass=new WrapperClass(UseID,LoginStatus);
                    UserState_Update.add(wrapperClass);
                }

                return UserState_Update; //List<WrapperClass> UserState_Update

            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }

        return null;
    }
</code>```

This is the response as JSON

```<code>{
    "status": "SUCCESS",
    "uData": [
        {
            "User_ID": "4",
            "login_status": "1",
            "lastseen": "0000-00-00 00:00:00"
        },
        {
            "User_ID": "1",
            "login_status": "0",
            "lastseen": "0000-00-00 00:00:00"
        },
        {
            "User_ID": "12",
            "login_status": "1",
            "lastseen": "0000-00-00 00:00:00"
        },
        {
            "User_ID": "33",
            "login_status": "0",
            "lastseen": "0000-00-00 00:00:00"
        }
    ]
}
</code>```

Is this right way to get user online state? (I know FCM is right way but FCM currently not ready on app server side)

UPDATE 2:-As code recommended by @XngPro i implement on doinBackground

```<code>Map<String,Online_Status_Wrapper.User> map=new HashMap<>();
    Online_Status_Wrapper wrapper=gson.fromJson(completeJSON,Online_Status_Wrapper.class);
                        Log.d(TAG,"Wrapper Get Data value "+wrapper.getuData());
                        Log.d(TAG,"Wrapper Get Status value "+wrapper.getStatus());

                        for (Online_Status_Wrapper.User u: wrapper.getuData()){
                            map.put(u.getUser_ID(),u);
                        }

                        Log.d(TAG,"State of Other User users "+map.get(12).getLogin_status());//HERE I AM GETTING NullPointerException
                        return map;
</code>```

答:
```<code>public class Test {

    public static void main(String[] args) {
        bar();
    }

    private static void bar() {
        String jsonStr = "{\"status\":\"SUCCESS\",\"uData\":[{\"User_ID\":\"4\",\"login_status\":\"1\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"1\",\"login_status\":\"0\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"12\",\"login_status\":\"1\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"33\",\"login_status\":\"0\",\"lastseen\":\"0000-00-00 00:00:00\"}]}";
        Gson gson = new Gson();
        UserFoo userFoo = gson.fromJson(jsonStr, UserFoo.class);
        Map<String, UserFoo.User> map = new HashMap<>();
        for (UserFoo.User u : userFoo.getUData()) {
            map.put(u.getUser_ID(), u);
        }
        System.out.println("userId: " + "12, loginState: " + map.get("12").getLogin_status());
    }

    public static class UserFoo {

        /**
         * status : SUCCESS
         * uData : [{"User_ID":"4","login_status":"1","lastseen":"0000-00-00 00:00:00"},{"User_ID":"1","login_status":"0","lastseen":"0000-00-00 00:00:00"},{"User_ID":"12","login_status":"1","lastseen":"0000-00-00 00:00:00"},{"User_ID":"33","login_status":"0","lastseen":"0000-00-00 00:00:00"}]
         */

        private String status;
        private List<User> uData;

        public String getStatus() {
            return status;
        }

        public void setStatus(String status) {
            this.status = status;
        }

        public List<User> getUData() {
            return uData;
        }

        public void setUData(List<User> uData) {
            this.uData = uData;
        }

        public static class User {
            /**
             * User_ID : 4
             * login_status : 1
             * lastseen : 0000-00-00 00:00:00
             */

            private String User_ID;
            private String login_status;
            private String lastseen;

            public String getUser_ID() {
                return User_ID;
            }

            public void setUser_ID(String User_ID) {
                this.User_ID = User_ID;
            }

            public String getLogin_status() {
                return login_status;
            }

            public void setLogin_status(String login_status) {
                this.login_status = login_status;
            }

            public String getLastseen() {
                return lastseen;
            }

            public void setLastseen(String lastseen) {
                this.lastseen = lastseen;
            }
        }
    }

}
</code>```

Print

Title: Get User online/offline state

Body:
I have chat app where i need to develop user online state and for this i am calling API in every 15 seconds on server, which will return all logged in users and their online state in 0(Offline) and 1(Online).

I need to show whether user is online or offline (leaves app not logged out) while chatting.I have 1 array list which shows when app is launch with all logged in user id and their details including their online state and i created second API which return users online state in JSON.I have following option to achieve users online state

Replace existing array list item:-I am getting User ID and their online state in JSON but i need to run loop in every 15 second which replace values in existing arraylist

Store JSON in someway where i can easily find user id and its state:- If i store JSON in array list i need to  run loop to find ID and its state which i dont want to,So which is best way to store JSON so i can easily get user state by its User ID.

Here is how i am getting JSON

protected List<WrapperClass> doInBackground(Void... params) {
        userSession=new UserSession(context,"Elaxer");
        UserState_Update=new ArrayList<>();

            String data = null;
            try {
                String ID=userSession.getUserID(); //Getting Value from shared pref
                data = URLEncoder.encode("User_ID", "UTF-8") + "=" + URLEncoder.encode(ID, "UTF-8");
                Log.d(TAG,"Login ID "+ ID);
                Log.d(TAG,"DO IN BACKGROUND START ");
                URL url=new URL(URL_Path_NearBy);
                connection= (HttpURLConnection) url.openConnection();
                Log.d(TAG,connection.toString());
                connection.setRequestMethod("POST");
                connection.setDoInput(true);
                connection.setDoOutput(true);

                //For POST Only - Begin
                OutputStream os = connection.getOutputStream();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
                writer.write(data);
                writer.flush();
                writer.close();
                os.close();
                connection.connect();

                InputStream inputStream=connection.getInputStream();
                reader=new BufferedReader(new InputStreamReader(inputStream));
                Log.d(TAG,"GET INPUT STREAM AND PUUTING INTO READER");
                String line;
                StringBuffer stringBuffer=new StringBuffer();
                while ((line=reader.readLine())!=null){
                    stringBuffer.append(line);

                }
                String completeJSON=stringBuffer.toString();
                Log.d(TAG,"JSON ARRAY START");

                JSONObject parentArray=new JSONObject(completeJSON);
                JSONArray jsonArray=parentArray.getJSONArray("uData");

                String LastSeen;
                int LoginStatus,User_ID;
                int Rec_Online_Status;

                for (int i = 0; i <jsonArray.length() ; i++) {
                    JSONObject childObject=jsonArray.getJSONObject(i);

                    LastSeen=childObject.getString("lastseen") ;
                    LoginStatus=childObject.getInt("login_status") ;
                    User_ID=childObject.getInt("User_ID");
                    String UseID= String.valueOf(User_ID);
                    Log.d(TAG,"JSON Values "+LastSeen+" "+LoginStatus+" "+User_ID);

                    WrapperClass wrapperClass=new WrapperClass(UseID,LoginStatus);
                    UserState_Update.add(wrapperClass);
                }

                return UserState_Update; //List<WrapperClass> UserState_Update

            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }

        return null;
    }

This is the response as JSON

{
    "status": "SUCCESS",
    "uData": [
        {
            "User_ID": "4",
            "login_status": "1",
            "lastseen": "0000-00-00 00:00:00"
        },
        {
            "User_ID": "1",
            "login_status": "0",
            "lastseen": "0000-00-00 00:00:00"
        },
        {
            "User_ID": "12",
            "login_status": "1",
            "lastseen": "0000-00-00 00:00:00"
        },
        {
            "User_ID": "33",
            "login_status": "0",
            "lastseen": "0000-00-00 00:00:00"
        }
    ]
}

Is this right way to get user online state? (I know FCM is right way but FCM currently not ready on app server side)

UPDATE 2:-As code recommended by @XngPro i implement on doinBackground

Map<String,Online_Status_Wrapper.User> map=new HashMap<>();
    Online_Status_Wrapper wrapper=gson.fromJson(completeJSON,Online_Status_Wrapper.class);
                        Log.d(TAG,"Wrapper Get Data value "+wrapper.getuData());
                        Log.d(TAG,"Wrapper Get Status value "+wrapper.getStatus());

                        for (Online_Status_Wrapper.User u: wrapper.getuData()){
                            map.put(u.getUser_ID(),u);
                        }

                        Log.d(TAG,"State of Other User users "+map.get(12).getLogin_status());//HERE I AM GETTING NullPointerException
                        return map;

Body:
public class Test {

    public static void main(String[] args) {
        bar();
    }

    private static void bar() {
        String jsonStr = "{\"status\":\"SUCCESS\",\"uData\":[{\"User_ID\":\"4\",\"login_status\":\"1\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"1\",\"login_status\":\"0\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"12\",\"login_status\":\"1\",\"lastseen\":\"0000-00-00 00:00:00\"},{\"User_ID\":\"33\",\"login_status\":\"0\",\"lastseen\":\"0000-00-00 00:00:00\"}]}";
        Gson gson = new Gson();
        UserFoo userFoo = gson.fromJson(jsonStr, UserFoo.class);
        Map<String, UserFoo.User> map = new HashMap<>();
        for (UserFoo.User u : userFoo.getUData()) {
            map.put(u.getUser_ID(), u);
        }
        System.out.println("userId: " + "12, loginState: " + map.get("12").getLogin_status());
    }

    public static class UserFoo {

        /**
         * status : SUCCESS
         * uData : [{"User_ID":"4","login_status":"1","lastseen":"0000-00-00 00:00:00"},{"User_ID":"1","login_status":"0","lastseen":"0000-00-00 00:00:00"},{"User_ID":"12","login_status":"1","lastseen":"0000-00-00 00:00:00"},{"User_ID":"33","login_status":"0","lastseen":"0000-00-00 00:00:00"}]
         */

        private String status;
        private List<User> uData;

        public String getStatus() {
            return status;
        }

        public void setStatus(String status) {
            this.status = status;
        }

        public List<User> getUData() {
            return uData;
        }

        public void setUData(List<User> uData) {
            this.uData = uData;
        }

        public static class User {
            /**
             * User_ID : 4
             * login_status : 1
             * lastseen : 0000-00-00 00:00:00
             */

            private String User_ID;
            private String login_status;
            private String lastseen;

            public String getUser_ID() {
                return User_ID;
            }

            public void setUser_ID(String User_ID) {
                this.User_ID = User_ID;
            }

            public String getLogin_status() {
                return login_status;
            }

            public void setLogin_status(String login_status) {
                this.login_status = login_status;
            }

            public String getLastseen() {
                return lastseen;
            }

            public void setLastseen(String lastseen) {
                this.lastseen = lastseen;
            }
        }
    }

}

Print


问:
C:\windows\SysWow64\CScript.exe window pop up
I created a macro in Excel and i am running it from a .vbs file. It's working fine on my laptop. I copied the same work on a new laptop and each time i am running the vbs file this window appears on the screen.

I have made some research and read that the situation i mentioned is happening when loading CheckNDISPort service on the startup. But i don't believe it's the reason because when i go to task manager and check in the startUp tab i don't find this service. Also when i restart my laptop i don't get this window, only when i am running my vbs file. I am sure there is any problem with my vbs file too because on the other laptops it's working fine.

Any suggestion please how to get ride of this pop up ? For now i am closing the window each time or ending the task from task manager but everytime i run it again so it pops up again.

Thank you very much.

答:
Windows Scripting Host has two interpreter front-ends, wscript.exe and cscript.exe. cscript.exe is a console application and if cscript.exe is set as the default a console window will open every time you execute a script.

Run cmd.exe elevated as administrator and run wscript.exe //h:wscript.

Depending on the Windows version, you might also be able to right-click a .vbs file, select "Open with...", choose %windir%\system32\wscript.exe and check the "default" checkbox.


问:
Python: My program could print, but return None?
I have some problems when calling a function.

```<code>import random
board = []
solution=[]

def isConflict(x, y):

    for (i, j) in board:
        if x == i:
            return True
        if y == j:
            return True
        if abs(x - i) == abs(y - j):
            return True
    else:
        return False

def solve(x,y):
    for y in range(1, 9):
        if isConflict(x, y)==False:
            board.append((x, y))
            solve(x + 1,y)
            board.remove((x,y))
    if x > 8:
        solution.append(list(board))
        if len(solution)==92:
                return solution[random.randint(1,91)]

a=solve(1,1)
print(a)
</code>```

This will give a None. However if I change the last part into:

```<code>    if x > 8:
        solution.append(list(board))
        if len(solution)==92:
                print(solution[random.randint(1,91)])

solve(1,1)
</code>```

I could get the answer.
Therefore I couldn't do anything with the function because it always turns out to be a Nonetype and I want to use it in other functions. What shall I do? Many thanks!!

答:
It seemed magical for a moment, but then I noticed that solve is recursive. The condition is true, but not in the topmost invocation.

You should do something with the value of solve instead of just calling it. I'd change it to this:

```<code>def solve(x,y):
    if x > 8:
        solution.append(list(board))
        if len(solution)==92:
            return solution[random.randint(1,91)]

    for y in range(1, 9):
        if isConflict(x, y)==False:
            board.append((x, y))
            s = solve(x + 1,y)
            board.remove((x,y))

            if s is not None:
                return s
</code>```

Usually something is wrong if all paths of a function do not return a value.

Body:
I have some problems when calling a function.

import random
board = []
solution=[]

def isConflict(x, y):

    for (i, j) in board:
        if x == i:
            return True
        if y == j:
            return True
        if abs(x - i) == abs(y - j):
            return True
    else:
        return False

def solve(x,y):
    for y in range(1, 9):
        if isConflict(x, y)==False:
            board.append((x, y))
            solve(x + 1,y)
            board.remove((x,y))
    if x > 8:
        solution.append(list(board))
        if len(solution)==92:
                return solution[random.randint(1,91)]

a=solve(1,1)
print(a)

This will give a None. However if I change the last part into:

    if x > 8:
        solution.append(list(board))
        if len(solution)==92:
                print(solution[random.randint(1,91)])

solve(1,1)

I could get the answer.
Therefore I couldn't do anything with the function because it always turns out to be a Nonetype and I want to use it in other functions. What shall I do? Many thanks!!

Body:
It seemed magical for a moment, but then I noticed that solve is recursive. The condition is true, but not in the topmost invocation.

You should do something with the value of solve instead of just calling it. I'd change it to this:

def solve(x,y):
    if x > 8:
        solution.append(list(board))
        if len(solution)==92:
            return solution[random.randint(1,91)]

    for y in range(1, 9):
        if isConflict(x, y)==False:
            board.append((x, y))
            s = solve(x + 1,y)
            board.remove((x,y))

            if s is not None:
                return s

Usually something is wrong if all paths of a function do not return a value.


问:
My Domain Emails using Google Apps Business are getting sent to spam by the gmail recipient
I just found out my domain's emails have been going to the spam folder of gmail recipients. I did some research and I put the following in my DNS records for my domain name:

```<code>TXT - "v=spf1 include:_spf.google.com ~all"
</code>```

I'm not sure if I have to put anything before the spf like my server's IP address or a or mx in some configurations I see. I mainly use my google apps domain email by using my plain gmail account and set "Send As" to send from the domain specific emails.

Is there something else I am missing or overlooking that I need to do to resolve this issue?

答:
If you're only using google apps to send emails then that's the correct SPF record.

If you want to be sure, the best thing you can do is send an email to

```<code>mailtest@unlocktheinbox.com
check-auth@verifier.port25.com
</code>```

They are know as reflectors and will auto-respond with your configuration, letting you know if you have your SPF set up correctly.

If you're unsure of what you need just use an SPF Wizard, but I think based on your description you're 100% fine. The MX and A just tells the receiving mail server that if the mail comes from you MX or A of your domain, then it's a good email, but you're sending from google, so you wouldn't need it.

Also with GMAIL in-boxing takes time and SPF isn't the magic cure, but it helps.

Body:
I just found out my domain's emails have been going to the spam folder of gmail recipients. I did some research and I put the following in my DNS records for my domain name:

TXT - "v=spf1 include:_spf.google.com ~all"

I'm not sure if I have to put anything before the spf like my server's IP address or a or mx in some configurations I see. I mainly use my google apps domain email by using my plain gmail account and set "Send As" to send from the domain specific emails.

Is there something else I am missing or overlooking that I need to do to resolve this issue?

Body:
If you're only using google apps to send emails then that's the correct SPF record.

If you want to be sure, the best thing you can do is send an email to

mailtest@unlocktheinbox.com
check-auth@verifier.port25.com

They are know as reflectors and will auto-respond with your configuration, letting you know if you have your SPF set up correctly.

If you're unsure of what you need just use an SPF Wizard, but I think based on your description you're 100% fine. The MX and A just tells the receiving mail server that if the mail comes from you MX or A of your domain, then it's a good email, but you're sending from google, so you wouldn't need it.

Also with GMAIL in-boxing takes time and SPF isn't the magic cure, but it helps.


问:
Visual C++: function definition for 'mouse_event' not found
Trying to use some Windows API in my Visual C++ project, encountering compilation issues.

Within my class I have the following code:

```<code>public:
[System::Runtime::InteropServices::DllImport("user32.dll")]
static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwextrainfo);
</code>```

This is all I have in my class as I'm currently trying to get mouse_event() to work.

"extern" is throwing:

more than one storage class specified

"mouse_event" is throwing the linking error:

Function definition for "mouse_event" not found

I've declared mouse event as extern, included Windows.h and imported user32.dll, is this not all that's required to link to the definition of mouse_event() within user32.dll?

When changing static extern to just extern, it throws:

Invalid storage class for a class member

Shouldn't extern be ok in a class definition when used on a member's declaration?

I've seen very similar code implementation of this function on stackoverflow  before.

If it helps, my class is defined as "ref class"

Any thoughts?

答:
I assume you are trying to emulate interop syntax you found as it pertains to C#? Such action in C++ is a little more involved:
https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx

EDITED FOR EXPOSITION:
If this isn't the case, please specify your source inspiration for such an approach, or the rest of your class, because as it stands, I don't see this working in C++, visual or not. That isn't even an extant C++ namespace you're targeting there, but it is a .NET one, substantiating my assumption...

Body:
Trying to use some Windows API in my Visual C++ project, encountering compilation issues.

Within my class I have the following code:

public:
[System::Runtime::InteropServices::DllImport("user32.dll")]
static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwextrainfo);

This is all I have in my class as I'm currently trying to get mouse_event() to work.

"extern" is throwing:

more than one storage class specified

"mouse_event" is throwing the linking error:

Function definition for "mouse_event" not found

I've declared mouse event as extern, included Windows.h and imported user32.dll, is this not all that's required to link to the definition of mouse_event() within user32.dll?

When changing static extern to just extern, it throws:

Invalid storage class for a class member

Shouldn't extern be ok in a class definition when used on a member's declaration?

I've seen very similar code implementation of this function on stackoverflow  before.

If it helps, my class is defined as "ref class"

Any thoughts?


问:
SQL UPDATE WITH CONCATENE FIELD
Hy Everyone,

I have the follwing table

```<code>mysql> select * from recipes;
+------+-------+
| id   | direct|
+------+-------+
|    1 | max   |
|    2 | linda |
|    3 | sam   |
|    4 | henry |
+------+-------+
</code>```

But a need to update all direct field and put {{  }} at the beginning and at the end of the field.

```<code>+------+-----------+
| id   | direct    |
+------+-----------+
|    1 | {{max}}   |
|    2 | {{linda}} |
|    3 | {{sam}}   |
|    4 | {{henry}} |
+------+-----------+
</code>```

How can I do that?

I tried UPDATE recipes SET direct = '{"step": [{ "description": "'+direct+'","image": ""}]}', but it does not work for me.

Please help me!!!

答:
try this.. using concat</p>

```<code>update recipes set direct = concat('{{',direct,'}}')
</code>```

Title: SQL UPDATE WITH CONCATENE FIELD

Body:
Hy Everyone,

I have the follwing table

mysql> select * from recipes;
+------+-------+
| id   | direct|
+------+-------+
|    1 | max   |
|    2 | linda |
|    3 | sam   |
|    4 | henry |
+------+-------+

But a need to update all direct field and put {{  }} at the beginning and at the end of the field.

+------+-----------+
| id   | direct    |
+------+-----------+
|    1 | {{max}}   |
|    2 | {{linda}} |
|    3 | {{sam}}   |
|    4 | {{henry}} |
+------+-----------+

How can I do that?

I tried UPDATE recipes SET direct = '{"step": [{ "description": "'+direct+'","image": ""}]}', but it does not work for me.

Please help me!!!

Body:
try this.. using concat

update recipes set direct = concat('{{',direct,'}}')